题目链接: http://poj.org/problem?id=1511
题目大意:
给定一个n(n<=1000000)个点的有向图,1为起点,求 1到所有点的最短路径之和 + 所有点到1的最短路径之和;
分析:
对于原图求一次最短路,再对反图求一次最短路即可;
最短路可以使用spfa或者dijkstra+heap,下面都可以作为模版了很好用,深刻理解算法原理是关键;
尤其是dijkstra+heap有多种写法,用下面的写法是比较好的(来自fhq队长);
代码:
poj1511 SPFA代码
1 /*1511 Accepted 44324K 1688MS C++ 1871B 2012-07-02 17:29:59*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <vector> 8 using namespace std; 9 10 #define mpair make_pair 11 #define pii pair<int,int> 12 #define MM(a,b) memset(a,b,sizeof(a)); 13 typedef long long lld; 14 typedef unsigned long long u64; 15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;} 16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;} 17 #define maxn 1000050 18 19 int n,top,top2; 20 struct Edge{ 21 int v,w; 22 Edge *next; 23 } *adj[maxn], e[maxn], *a2[maxn], e2[maxn]; 24 void addedge(int u,int v,int w){ 25 Edge *p= &e[top++]; 26 p->v= v, p->w= w, p->next= adj[u], adj[u]= p; 27 } 28 void add2(int u,int v,int w){ 29 Edge *p= &e2[top2++]; 30 p->v= v, p->w= w, p->next= a2[u], a2[u]= p; 31 } 32 33 const lld inf= 100000000000000LL; 34 lld d[maxn]; 35 int que[maxn+10]; 36 bool vis[maxn]; 37 void spfa(Edge *(*a)){ 38 int i, h=0, t= 0; 39 for(i=1;i<=n;++i) d[i]= inf, vis[i]= 0; 40 que[t++]= 1; 41 vis[1]= 1; 42 d[1]= 0; 43 while( h!=t ){ 44 int u= que[h++]; if( h==maxn ) h= 0; 45 vis[u]= 0; ///!!! 46 for(Edge *p= a[u];p;p=p->next){ 47 int v= p->v, w= p->w; 48 if( up_min( d[v], d[u]+p->w ) && !vis[v] ){ 49 vis[v]= 1; 50 que[t++]= v; if( v==maxn ) v= 0; 51 } 52 } 53 } 54 } 55 56 int main() 57 { 58 //freopen("poj1511.in","r",stdin); 59 int T,x,y,w,m,i; 60 cin>>T; 61 while(T--){ 62 cin>>n>>m; 63 top= top2= 0; 64 for(i=1;i<=n;++i) adj[i]= a2[i]= 0; 65 while(m--){ 66 scanf("%d%d%d", &x, &y, &w); 67 addedge( x, y, w ); 68 add2( y, x, w ); 69 } 70 lld ans= 0; 71 spfa( adj ); 72 for(i=1;i<=n;++i) ans+= d[i]; 73 spfa( a2 ); 74 for(i=1;i<=n;++i) ans+= d[i]; 75 cout<< ans <<endl; 76 } 77 }
poj1511 dijkstra+heap
1 /*1511 Accepted 39440K 1860MS C++ 1958B 2012-07-02 18:17:29*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <vector> 8 #include <queue> 9 using namespace std; 10 11 #define mpair make_pair 12 #define pii pair<int,int> 13 #define MM(a,b) memset(a,b,sizeof(a)); 14 typedef long long lld; 15 typedef unsigned long long u64; 16 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;} 17 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;} 18 #define maxn 1000050 19 20 int n,top,top2; 21 struct Edge{ 22 int v,w; 23 Edge *next; 24 } *adj[maxn], e[maxn], *a2[maxn], e2[maxn]; 25 void addedge(int u,int v,int w){ 26 Edge *p= &e[top++]; 27 p->v= v, p->w= w, p->next= adj[u], adj[u]= p; 28 } 29 void add2(int u,int v,int w){ 30 Edge *p= &e2[top2++]; 31 p->v= v, p->w= w, p->next= a2[u], a2[u]= p; 32 } 33 34 const lld inf= 100000000000000LL; 35 lld d[maxn]; 36 bool vis[maxn]; 37 typedef pair< lld, int > plld; 38 priority_queue< plld, vector< plld >, greater< plld > >Q; 39 void dijkstra(Edge *(*a)){ 40 for(int i=1;i<=n;++i) d[i]= inf; 41 d[1]= 0; 42 while( !Q.empty() ) Q.pop(); 43 Q.push( mpair( 0, 1 ) ); 44 while( !Q.empty() ){ 45 lld dd= Q.top().first; 46 int u= Q.top().second; 47 Q.pop(); 48 if( dd != d[u] ) continue; 49 for(Edge *p= a[u];p;p= p->next){ 50 int v= p->v; 51 if( up_min( d[v], d[u] + p->w ) ) 52 Q.push( mpair( d[v], v ) ); 53 } 54 } 55 } 56 57 int main() 58 { 59 //freopen("poj1511.in","r",stdin); 60 int T,x,y,w,m,i; 61 cin>>T; 62 while(T--){ 63 cin>>n>>m; 64 top= top2= 0; 65 for(i=1;i<=n;++i) adj[i]= a2[i]= 0; 66 while(m--){ 67 scanf("%d%d%d", &x, &y, &w); 68 addedge( x, y, w ); 69 add2( y, x, w ); 70 } 71 lld ans= 0; 72 dijkstra( adj ); 73 for(i=1;i<=n;++i) ans+= d[i]; 74 dijkstra( a2 ); 75 for(i=1;i<=n;++i) ans+= d[i]; 76 cout<< ans <<endl; 77 } 78 }
一毛原创作品,转载请注明出处。