题目链接:http://poj.org/problem?id=1511
题目大意:给你n个点,m条边(1<=n<=m<=1e6),每条边长度不超过1e9。问你从起点到各个点以及从各个点到起点的最小路程总和。
解题思路:这里用了优先队列优化的dijkstra复杂度mlogn,从起点到个点最短路径直接算就好了,算各个点到起点的最短路径,只要把边的方向反一下,再算一次从起点到个点最短路径就好了。
Dijkstra:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<functional> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 typedef long long LL; 9 typedef pair<int,int> p; 10 const int N=1e6+5; 11 const int INF=1<<30;//这里不能比1e9小 12 struct edge{ 13 int to,cost; 14 }; 15 16 vector<edge>eg[N]; 17 int V,E; 18 bool used[N]; 19 int d[N]; 20 int a[N],b[N],c[N]; 21 22 void dijkstra(int s){ 23 for(int i=1;i<=V;i++){ 24 d[i]=INF; 25 used[i]=false; 26 } 27 d[s]=0; 28 29 priority_queue<p,vector<p>,greater<p> >q; 30 q.push(p(0,s)); 31 while(!q.empty()){ 32 p p1=q.top(); 33 q.pop(); 34 int v=p1.second; 35 if(used[v]) continue; 36 used[v]=true; 37 for(int i=0;i<eg[v].size();i++){ 38 edge e=eg[v][i]; 39 if(d[e.to]>d[v]+e.cost){ 40 d[e.to]=d[v]+e.cost; 41 q.push(p(d[e.to],e.to)); 42 } 43 } 44 } 45 } 46 47 int main(){ 48 int q; 49 scanf("%d",&q); 50 while(q--){ 51 scanf("%d %d",&V,&E); 52 for(int i=1;i<=V;i++){ 53 eg[i].clear(); 54 } 55 for(int i=1;i<=E;i++){ 56 scanf("%d%d%d",&a[i],&b[i],&c[i]); 57 edge gg; 58 gg.to=b[i],gg.cost=c[i]; 59 eg[a[i]].push_back(gg); 60 } 61 dijkstra(1); 62 LL sum=0; 63 for(int i=1;i<=V;i++){ 64 sum+=d[i]; 65 } 66 //将边的方向反一下 67 for(int i=1;i<=V;i++){ 68 eg[i].clear(); 69 } 70 for(int i=1;i<=E;i++){ 71 edge gg; 72 gg.to=a[i],gg.cost=c[i]; 73 eg[b[i]].push_back(gg); 74 } 75 dijkstra(1); 76 for(int i=1;i<=V;i++){ 77 sum+=d[i]; 78 } 79 printf("%lld ",sum); 80 } 81 }
SPFA:
1 #include<iostream> 2 #include<queue> 3 #include<vector> 4 using namespace std; 5 const int INF=1<<30; 6 const int N=1e6+5; 7 8 struct edge{ 9 int to,cost; 10 }; 11 12 vector<edge>eg[N]; 13 int V,E; 14 bool used[N];//是否在队列中 15 int d[N]; 16 int a[N],b[N],c[N]; 17 18 void spfa(int s){ 19 for(int i=1;i<=V;i++){ 20 d[i]=INF; 21 used[i]=false; 22 } 23 d[s]=0; 24 25 queue<int>q; 26 q.push(s); 27 used[s]=true; 28 while(!q.empty()){ 29 int v=q.front(); 30 q.pop(); 31 used[v]=false; 32 for(int i=0;i<eg[v].size();i++){ 33 edge e=eg[v][i]; 34 if(d[e.to]>d[v]+e.cost){ 35 d[e.to]=d[v]+e.cost; 36 if(!used[e.to]){ 37 used[e.to]=true; 38 q.push(e.to); 39 } 40 } 41 } 42 } 43 } 44 45 int main(){ 46 int q; 47 scanf("%d",&q); 48 while(q--){ 49 scanf("%d%d",&V,&E); 50 for(int i=1;i<=V;i++){ 51 eg[i].clear(); 52 } 53 for(int i=1;i<=E;i++){ 54 scanf("%d%d%d",&a[i],&b[i],&c[i]); 55 edge gg; 56 gg.to=b[i],gg.cost=c[i]; 57 eg[a[i]].push_back(gg); 58 } 59 spfa(1); 60 long long sum=0; 61 for(int i=1;i<=V;i++){ 62 sum+=d[i]; 63 } 64 //方向反一下 65 for(int i=1;i<=V;i++){ 66 eg[i].clear(); 67 } 68 for(int i=1;i<=E;i++){ 69 edge gg; 70 gg.to=a[i],gg.cost=c[i]; 71 eg[b[i]].push_back(gg); 72 } 73 spfa(1); 74 for(int i=1;i<=V;i++){ 75 sum+=d[i]; 76 } 77 printf("%lld ",sum); 78 } 79 }