TOJ 2217. Invitation Cards【最短路dijkstra+堆优化或者SPFA】

 

TOJ 2217. Invitation Cards【最短路dijkstra+堆优化或者SPFA】

分类: 【图论专辑】   337人阅读  评论(0)  收藏  举报

                 就是一个很明显的最短路,大意是给出一个有向图,求从一个点到其他所有点的最短路的和以及其他所有点到该点的最短路的和。

                 思路就是两遍最短路,第二遍对反图求即可。关键是点数最多为1000000,所以N^2的dijkstra是不行的,需要用SPFA或者堆优化的dijkstra。两种方法我都试过了,效率差不多,但是当图稠密起来后堆优化的dijkstra要比SPFA更快。

                 下面给出两种方法的代码。

dijkstra+堆优化:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <vector>  
  4. #include <queue>  
  5. #define MAXN 1000002  
  6. using namespace std;  
  7. bool flag[MAXN];  
  8. int dist[MAXN],n;  
  9. struct Node{  
  10.     int id,val;  
  11.     Node(){}  
  12.     Node(int _id,int _val):id(_id),val(_val){}  
  13.     bool operator<(const Node &a)const{                //重载<,使优先队列队首始终是val最小的元素  
  14.         return val > a.val;  
  15.     }  
  16. };  
  17. struct Old{  
  18.     int u,v,w;  
  19.     Old(){}  
  20.     Old(int _u,int _v,int _w):u(_u),v(_v),w(_w){}  
  21. }a[MAXN];  
  22. struct Edge{  
  23.     int v,cost;                                           
  24.     Edge(){}  
  25.     Edge(int _v,int _cost):v(_v),cost(_cost){}  
  26. };  
  27. vector<Edge>mp[MAXN];                                        //mp[i][j].v表示i的第j条边连接的是顶点v,权值为mp[i][j].cost  
  28. long long dijkstra(int s){  
  29.     int i,j,k,v,cost;  
  30.     Node tep,tep2;  
  31.     memset(flag,false,sizeof(flag));  
  32.     memset(dist,0x7f,sizeof(dist));  
  33.     priority_queue<Node>que;  
  34.     while(!que.empty()) que.pop();                                              //清空队列  
  35.     dist[s] = 0;  
  36.     tep.id = s;  
  37.     tep.val = 0;  
  38.     que.push(tep);                                                               //起点入队  
  39.     while(!que.empty()){  
  40.         tep = que.top();  
  41.         que.pop();  
  42.         if(flag[tep.id]) continue;                                          //如果tep.id已经在集合中,不用拿出  
  43.         flag[tep.id] = true;                                                  //将tep.id放入集合  
  44.         for(i = 0;i < mp[tep.id].size(); i++){  
  45.             v = mp[tep.id][i].v;  
  46.             cost = mp[tep.id][i].cost;  
  47.             if(!flag[v] && dist[v] > dist[tep.id] + cost){                //松弛  
  48.                 dist[v] = dist[tep.id] + cost;  
  49.                 tep2.id = v;  
  50.                 tep2.val = dist[v];  
  51.                 que.push(tep2);                                     //加入集合  
  52.             }  
  53.         }  
  54.     }  
  55.     long long sum = 0;  
  56.     for(i = 1;i <= n; i++) sum += dist[i];  
  57.     return sum;  
  58. }  
  59. int main()  
  60. {  
  61.     int i,j,k,m,T;  
  62.         int u,v,w;  
  63.         long long ans;  
  64.         scanf("%d",&T);  
  65.         while(T--){  
  66.                 scanf("%d%d",&n,&m);  
  67.                 for(i = 1;i <= n; i++) mp[i].clear();  
  68.                 for(i = 1;i <= m;i++){  
  69.                         scanf("%d%d%d",&u,&v,&w);  
  70.                         a[i] = Old(u,v,w);  
  71.                         mp[u].push_back(Edge(v,w));  
  72.                 }  
  73.                 ans = 0;  
  74.                 ans += dijkstra(1);  
  75.                 for(i = 1;i <= n; i++) mp[i].clear();  
  76.                 for(i = 1;i <= m; i++){  
  77.                         u = a[i].u;  
  78.                         v = a[i].v;  
  79.                         w = a[i].w;  
  80.                         mp[v].push_back(Edge(u,w));  
  81.                 }  
  82.                 ans += dijkstra(1);  
  83.                 printf("%lld/n",ans);  
  84.         }  
  85. }  

 

SPFA:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <vector>  
  4. #define MAXN 1000002  
  5. using namespace std;  
  6. int dist[MAXN],que[MAXN];  
  7. bool flag[MAXN];  
  8. int head,tail,n;  
  9. struct old{  
  10.         int u,v,w;  
  11.         old(){}  
  12.         old(int a,int b,int c):u(a),v(b),w(c){}  
  13. }a[MAXN];  
  14. struct Edge{  
  15.         int id,cost;  
  16.         Edge(){}  
  17.         Edge(int a,int b):id(a),cost(b){}  
  18. };  
  19. vector<Edge>mp[MAXN];  
  20. long long SPFA(int s){  
  21.         int i,j,k,tep,v;  
  22.         memset(flag,false,sizeof(flag));  
  23.         memset(dist,0x7f,sizeof(dist));  
  24.         head = tail = 0;  
  25.         dist[s] = 0;  
  26.         flag[s] = true;  
  27.         que[tail++] = s;  
  28.         while(head != tail){  
  29.                 tep = que[head++];  
  30.                 if(head >= MAXN) head = 0;  
  31.                 flag[tep] = false;  
  32.                 for(i = 0;i < mp[tep].size(); i++){  
  33.                         v = mp[tep][i].id;  
  34.                         if(dist[v] > dist[tep] + mp[tep][i].cost){  
  35.                                 dist[v] = dist[tep] + mp[tep][i].cost;  
  36.                                 if(!flag[v]){  
  37.                                         que[tail++] = v;  
  38.                                         if(tail >= MAXN) tail = 0;  
  39.                                         flag[v] = true;  
  40.                                 }  
  41.                         }  
  42.                 }  
  43.         }  
  44.         long long sum = 0;  
  45.         for(i = 1;i <= n; i++) sum += dist[i];  
  46.         return sum;  
  47. }  
  48. int main()  
  49. {  
  50.         int i,j,k,m,T;  
  51.         int u,v,w;  
  52.         long long ans;  
  53.         scanf("%d",&T);  
  54.         while(T--){  
  55.                 scanf("%d%d",&n,&m);  
  56.                 for(i = 1;i <= n; i++) mp[i].clear();  
  57.                 for(i = 1;i <= m;i++){  
  58.                         scanf("%d%d%d",&u,&v,&w);  
  59.                         a[i] = old(u,v,w);  
  60.                         mp[u].push_back(Edge(v,w));  
  61.                 }  
  62.                 ans = 0;  
  63.                 ans += SPFA(1);  
  64.                 for(i = 1;i <= n; i++) mp[i].clear();  
  65.                 for(i = 1;i <= m; i++){  
  66.                         u = a[i].u;  
  67.                         v = a[i].v;  
  68.                         w = a[i].w;  
  69.                         mp[v].push_back(Edge(u,w));  
  70.                 }  
  71.                 ans += SPFA(1);  
  72.                 printf("%lld/n",ans);  
  73.         }  
  74. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值