Invitation Cards【最短路】

 

题目大意:

给你一个N个点的图,求1点到其他每个点最短路权值之和sum1,然后再求反向最短路(其他所有点到1点最短距离)之和sum2。输出sum1+sum2

 

解题思路:

别人说的题意,正好最短路也忘了,就用SPFA写了一下。结果SPFA忘了。。。问了别人,算是懂了。

所谓的SPFA,就是bellman-ford的优化,因为bellman-ford是循环更新每条边n-1次(循环次数固定),但是效率很低,因为不可能每条边都需要更新这么多次吧。所以,出现了SPFA。SPFA的改进之处在于,我加入队列的元素都是已经松弛过,最短距离减小的点,我每次取出对头,更新所以经过这个节点的其他点,如果其他节点的最短距离通过这个队头的点能变小,就松弛。不能就遍历其他点。这样,更新的次数大大减少。

之前我的SPFA是用邻接矩阵实现的,效率之挫就不多说了,因为没有充分利用邻接表的优势,因为邻接矩阵我必须逐个遍历,才能知道两点之间是否存在边,而邻接表存储的就是两点之间相连的边。

这样,SPFA+邻接表的组合就变得更加强大。。。。

总结就是:

最短路题目,最好都使用邻接表+SPFA。这样,差不多就能解决了。(除非特别出数据专门卡SPFA!~~还没遇到~~~~)

 

代码如下:

 

[cpp] view plaincopyprint?
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<climits>  
  4. #include<cstring>  
  5. #include<queue>  
  6. #include<cmath>  
  7. usingnamespace std; 
  8.  
  9. #define CLR(arr, what) memset(arr, what, sizeof(arr))  
  10. constint N = 1000010; 
  11. constlonglong MAX = 10000000000000005; //数据太大。10亿*100W  
  12.  
  13. int Head[N], Next[N], Key[N], Num[N], num; 
  14. longlong dis[N]; 
  15. bool visit[N]; 
  16. int nodenum, edgenum; 
  17.  
  18. struct Edge //结构体存图,方便反向建边  
  19.     int u, v; 
  20.     int weight; 
  21. }edge[N]; 
  22.  
  23. void add(int u, int v, int cost) //u,v之间加入权值为cost的边  
  24.     Key[num] = cost; 
  25.     Next[num] = Head[u]; 
  26.     Num[num] = v; 
  27.     Head[u] = num++; 
  28.  
  29. void init() 
  30.     num = 0; 
  31.     CLR(Head, -1); 
  32.     for(int i = 1; i <= nodenum; ++i) 
  33.         dis[i] = MAX; 
  34.  
  35. longlong SPFA(int start) 
  36.     longlong total = 0; 
  37.     int temp; 
  38.     queue<int> q; 
  39.     while(!q.empty()) 
  40.         q.pop(); 
  41.     CLR(visit, false); 
  42.  
  43.     dis[start] = 0; 
  44.     visit[start] = true
  45.  
  46.     q.push(start); 
  47.     while(!q.empty()) 
  48.     { 
  49.         temp = q.front(); 
  50.         q.pop(); 
  51.         visit[temp] = false
  52.         for(int i = Head[temp]; i != -1; i = Next[i]) //邻接表实现  
  53.         { 
  54.             if(dis[Num[i]] > dis[temp] + Key[i]) 
  55.             { 
  56.                 dis[Num[i]] = dis[temp] + Key[i]; 
  57.                 if(!visit[Num[i]]) 
  58.                 { 
  59.                     q.push(Num[i]); 
  60.                     visit[Num[i]] = true
  61.                 } 
  62.             } 
  63.         } 
  64.     } 
  65.     for(int i = 1; i <= nodenum; ++i) 
  66.         total += dis[i]; 
  67.     return total; 
  68.  
  69. int main() 
  70.     int ncase; 
  71.     int top; 
  72.     longlong answer; 
  73.     scanf("%d", &ncase); 
  74.     while(ncase--) 
  75.     { 
  76.         top = answer = 0; 
  77.         scanf("%d%d", &nodenum, &edgenum); 
  78.         init(); 
  79.         for(int i = 0; i < edgenum; ++i) 
  80.         { 
  81.             scanf("%d %d %d", &edge[top].u, &edge[top].v, &edge[top].weight); 
  82.             add(edge[top].u, edge[top].v, edge[top].weight); 
  83.             top++; 
  84.         } 
  85.         answer += SPFA(1); 
  86.         init(); 
  87.         for(int i = 0; i < top; ++i) //反向图  
  88.             add(edge[i].v, edge[i].u, edge[i].weight); 
  89.         answer += SPFA(1); 
  90.         printf("%lld\n", answer); 
  91.     } 
  92.     return 0; 
posted @ 2012-11-10 14:17  燕笑语兮  阅读(206)  评论(0编辑  收藏  举报