这题开始用没有优化的迪杰斯特拉喜闻乐见的超时了,然后我用bellmanford算法按理说时间复杂度更大但是书上说往往只要很短的时间就可以求出最短路。
所以我用了这个算法但是我对这个算法还是不熟套了模板。这题数据应该出水了,不然这个算法时间复杂度挺高的,应该过不了。应该是迪杰斯特拉的优化,一会写个迪杰斯特拉的优化后的算法看看应该可以过。
Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV)
BellmanFord:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE) SPFA:适用于权值有负值,且没有负圈的图的单源最短路径,论文中的复杂度O(kE),k为每个节点进入Queue的次数,且k一般<=2,
但此处的复杂度证明是有问题的,其实SPFA的最坏情况应该是O(VE). Floyd:每对节点之间的最短路径。
/*
ID: jinbo wu
TASK:butter
LANG:C++
*/
#include<bits/stdc++.h>
using namespace std;
int n,p,c;
vector<pair<int,int> >g[805];
int a[805];
bool vis[805];
int d[805];
int Bellman_Ford(int m)
{
queue<int> q;
for(int i=0;i<=p;i++) d[i]=(i==m? 0 : 10000);
q.push(m);
while(!q.empty())
{
int x=q.front(); q.pop();
vis[x]=0;
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i].first;
if(d[v]>d[x]+g[x][i].second)
{
d[v]=d[x]+g[x][i].second;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
ans+=d[a[i]];
return ans;
}
int main()
{
freopen("butter.in","r",stdin);
freopen("butter.out","w",stdout);
int u,v,w;
cin>>n>>p>>c;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=c;i++)
{
cin>>u>>v>>w;
g[u].push_back(make_pair(v,w));
g[v].push_back(make_pair(u,w));
}
int ans=1000000;
for(int i=1;i<=p;i++)
{
int temp=Bellman_Ford(i);
ans=min(ans,temp);
}
cout<<ans<<endl;
}
这是该程序的运行时间
下面是用迪杰斯特拉算法经过优选队列优化过后的代码
/*
ID: jinbo wu
TASK:butter
LANG:C++
*/
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int> > g[805];
int n,p,c;
bool done[805];
int d[805];
int a[805];
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> > q;
int dij(int m)
{
memset(done,0,sizeof(done));
for(int i=1;i<=p;i++) d[i]=(i==m ? 0 :10000);
q.push(make_pair(d[m],m));
while(!q.empty())
{
pair<int,int> u=q.top();q.pop();
int x=u.second;
if(done[x]) continue;
done[x]=1;
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i].first;
if(d[v]>d[x]+g[x][i].second)
{
d[v]=d[x]+g[x][i].second;
q.push(make_pair(d[v],v));
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
ans+=d[a[i]];
return ans;
}
int main()
{
freopen("butter.in","r",stdin);
freopen("butter.out","w",stdout);
int u,v,w;
cin>>n>>p>>c;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=c;i++)
{
cin>>u>>v>>w;
g[u].push_back(make_pair(v,w));
g[v].push_back(make_pair(u,w));
}
int ans=10000000;
for(int i=1;i<=p;i++)
{
int temp=dij(i);
ans=min(ans,temp);
}
cout<<ans<<endl;
}
经过优化过后的迪杰斯特拉为什么没有bellman_ford快?,普通迪杰斯特拉算法到test7的时候就0.5s多test8就超时了。