次短路径与次小生成树问题的简单解法

次短路径与次小生成树问题的简单解法

[次短路径]

次短路径可以看作是k短路径问题的一种特殊情况,求k短路径有Yen算法等较为复杂的方法,对于次短路径,可以有更为简易的方法。下面介绍一种求两个顶点之间次短路径的解法。

我们要对一个有向赋权图(无向图每条边可以看作两条相反的有向边)的顶点S到T之间求次短路径,首先应求出S的单源最短路径。遍历有向图,标记出可以在最短路径上的边,加入集合K。然后枚举删除集合K中每条边,求从S到T的最短路径,记录每次求出的路径长度值,其最小值就是次短路径的长度。

在这里我们以为次短路径长度可以等于最短路径长度,如果想等,也可以看作是从S到T有不止一条最短路径。如果我们规定求从S到T大于最短路径长度的次短路径,则答案就是每次删边后大于原最短路径的S到T的最短路径长度的最小值。

用Dijkstra+堆求单源最短路径,则每次求最短路径时间复杂度为O(Nlog(N+M) + M),所以总的时间复杂度为O(NM*log(N+M) + M^2)。该估计是较为悲观的,因为一般来说,在最短路径上的边的条数要远远小于M,所以实际效果要比预想的好。

[次小生成树]

类比上述次短路径求法,很容易想到一个“枚举删除最小生成树上的每条边,再求最小生成树”的直观解法。如果用Prim+堆,每次最小生成树时间复杂度为O(Nlog(N+M) + M),枚举删除有O(N)条边,时间复杂度就是O(N^2log(N+M) + N*M),当图很稠密时,接近O(N^3)。这种方法简易直观,但我们有一个更简单,而且效率更高的O(N^2+M)的解法,下面介绍这种方法。

首先求出原图最小生成树,记录权值之和为MinST。枚举添加每条不在最小生成树上的边(u,v),加上以后一定会形成一个环。找到环上权值第二大的边(即除了(u,v)以外的权值最大的边),把它删掉,计算当前生成树的权值之和。取所有枚举修改的生成树权值之和的最小值,就是次小生成树。

具体实现时,更简单的方法是从每个节点i遍历整个最小生成树,定义F[j]为从i到j的路径上最大边的权值。遍历图求出F[j]的值,然后对于添加每条不在最小生成树中的边(i,j),新的生成树权值之和就是MinST + w(i,j) - F[j],记录其最小值,则为次小生成树。

该算法的时间复杂度为O(N^2 + M)。由于只用求一次最小生成树,可以用最简单的Prim,时间复杂度为O(N^2)。算法的瓶颈不在求最小生成树,而在O(N^2+M)的枚举加边修改,所以用更好的最小生成树算法是没有必要的。

[次短路径与次小生成树的例题]

HAOI 2005 路由选择问题 直接求次短路径。

pku 3255 Roadblocks 稍微特殊的次短路径,允许边重复走。

Ural 1416 Confidential 求次小生成树的问题、

pku 1679 The Unique MST 判断最小生成树是否唯一。

[参考资料]

  • Amber的图论总结

BYVoid 原创讲解,转载请注明。


 

HDU 4756 次小生成树

分类: MST   81人阅读  评论(0)  收藏  举报

题意:给你n(n = 1000)个二维点,第一个点是power plant,还有n - 1个点是dormitories。然后现在知道有一条寝室到寝室的边是不能连的,但是我们不知道是哪条边,问这种情况下,最小生成树的最大值。

思路:有一种很朴素的算法就是枚举每一条被删除的边,然后做最小生成树,复杂度高的突破天际,显然不可以。

但是既然想到了上面的那种做法,再想一下就可以得到,我们还是枚举每一条被删除的边,只是这些边都是树边,所以关键就在于,删除这条边之后的图的最小生成树和原来的最小生成树的关系。

我们可以先预处理出来MINE[i][j], 表示点i 到点j 的最短的一条边。然后再预处理出来NMIN[i][j], 表示去掉边i -> j 之后,i -> j的最短边。

那么去掉一条边的增量就是NMIN[i][j] - MINE[i][j] 。然后取最大值即可。

[cpp]  view plain copy print ?
  1. #include <set>  
  2. #include <map>  
  3. #include <stack>  
  4. #include <cmath>  
  5. #include <queue>  
  6. #include <cstdio>  
  7. #include <string>  
  8. #include <vector>  
  9. #include <iomanip>  
  10. #include <cstring>  
  11. #include <iostream>  
  12. #include <algorithm>  
  13. #define Max 2505  
  14. #define FI first  
  15. #define SE second  
  16. #define ll long long  
  17. #define PI acos(-1.0)  
  18. #define inf 0x3fffffff  
  19. #define LL(x) ( x << 1 )  
  20. #define bug puts("here")  
  21. #define PII pair<int,int>  
  22. #define RR(x) ( x << 1 | 1 )  
  23. #define mp(a,b) make_pair(a,b)  
  24. #define mem(a,b) memset(a,b,sizeof(a))  
  25. #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )  
  26.   
  27. using namespace std;  
  28.   
  29. inline void RD(int &ret) {  
  30.     char c;  
  31.     int flag = 1 ;  
  32.     do {  
  33.         c = getchar();  
  34.         if(c == '-')flag = -1 ;  
  35.     } while(c < '0' || c > '9') ;  
  36.     ret = c - '0';  
  37.     while((c=getchar()) >= '0' && c <= '9')  
  38.         ret = ret * 10 + ( c - '0' );  
  39.     ret *= flag ;  
  40. }  
  41.   
  42. #define N 1111  
  43. #define M 111111  
  44. int st[M] ;  
  45. int top ;  
  46. double NMIN[N][N] ;  
  47. int x[N] , y[N] , cost , n ;  
  48. double Map[N][N] ;  
  49. double dis[N]  ;  
  50. bool vis[N] ;  
  51. vector<int>G[N] ;  
  52. priority_queue<kdq>qe ;  
  53. double mst = 0 ;  
  54. bool ismst[N][N] ;  
  55. double MINE[N][N] ;  
  56. double getdis(int i , int j){  
  57.     return sqrt(1.0 * (x[i] - x[j]) * (x[i] - x[j]) + 1.0 * (y[i] - y[j]) * (y[i] - y[j])) ;  
  58. }  
  59.   
  60. struct kdq{  
  61.     int s , e  ;  
  62.     double l ;  
  63.     bool operator <  (const kdq & fk)const {  
  64.         return l > fk.l ;  
  65.     }  
  66. } ;  
  67.   
  68. void Prim(){  
  69.     mst = 0 ;  
  70.     mem(ismst, 0) ;  
  71.     while(!qe.empty())qe.pop() ;  
  72.     for (int i = 0 ; i < n ; i ++ )dis[i] = Map[0][i] , vis[i] = 0 ,G[i].clear() ,qe.push((kdq){0 , i , dis[i]}) ;  
  73.     dis[0] = 0 , vis[0] = 1 ;  
  74.     while(!qe.empty()){  
  75.         kdq tp = qe.top() ; qe.pop() ;  
  76.         if(vis[tp.e])continue ;  
  77.         mst += Map[tp.s][tp.e] ;  
  78.         vis[tp.e] = 1 ;  
  79.         G[tp.s].push_back(tp.e) ; G[tp.e].push_back(tp.s) ;  
  80.         ismst[tp.e][tp.s] = ismst[tp.s][tp.e] = 1 ;  
  81.         MINE[tp.s][tp.e] = MINE[tp.e][tp.s] = inf ;//删除树边  
  82.         for (int i = 0 ; i < n ; i ++ )if(!vis[i] && dis[i] > Map[tp.e][i])dis[i] = Map[tp.e][i] , qe.push((kdq){tp.e , i , dis[i]}) ;  
  83.     }  
  84. }  
  85.   
  86. void dfs(int root , int fa , int now){  
  87.     int sz = G[now].size() ;  
  88.     for (int i = 0 ; i < sz ; i ++ ){  
  89.         int e = G[now][i] ;  
  90.         if(e != fa)dfs(root , now , e) , MINE[root][now] = min(MINE[root][now] , MINE[root][e]) ;  
  91.     }  
  92. }  
  93.   
  94. void dfs(int fa, int now){  
  95.     int fk = top ;  
  96.     st[ ++ top] = now ;int sz = G[now].size() ;  
  97.     for (int i = 0 ; i < sz ; i ++ ){  
  98.         int e = G[now][i] ; if(e != fa)dfs(now , e) ;  
  99.     }  
  100.     if(fa != -1){  
  101.         NMIN[now][fa] = NMIN[fa][now] = inf ;  
  102.         for (int i = fk + 1 ; i <= top ; i ++ )NMIN[now][fa] = NMIN[fa][now] = min(NMIN[fa][now] , MINE[st[i]][fa]) ;  
  103.     }  
  104. }  
  105. void solve(){  
  106.     cin >> n >> cost ;  
  107.     for (int i = 0 ; i < n ; i ++ )RD(x[i]) , RD(y[i]) ;  
  108.     for (int i = 0 ; i < n ; i ++ )  
  109.         for (int j = 0 ; j < n ; j ++ )  
  110.             MINE[i][j] = Map[i][j] = (i == j) ? 0 : getdis(i , j) ;  
  111.     Prim() ;  
  112.     for (int i = 0 ; i < n ; i ++ )dfs(i , -1 , i ) ;  
  113.     top = 0 ;  
  114.     dfs(-1 , 0) ;  
  115.     double ans = 0 ;  
  116.     for (int i = 0 ; i < n ; i ++ ){  
  117.         for (int j = 0 ; j < n ; j ++ ){  
  118.             if(i == 0 || j == 0)continue ;  
  119.             if(!ismst[i][j])continue ;  
  120.             ans = max(ans , NMIN[i][j] - Map[i][j]) ;  
  121.         }  
  122.     }  
  123.     printf("%.2f\n",(ans + mst) * cost) ;  
  124. }  
  125. int main() {  
  126.     int _ ; cin >> _ ; while(_ --)solve() ;  
  127.     return 0 ;  
 

hdu 4756 Install Air Conditioning(2013南京网络赛)

分类: dp   303人阅读  评论(4)  收藏  举报

题意就是求MST中删去一条边后,次小生成树最大的那颗。注意题中说了“ there are so many wires between two specific dormitories” 。也就是说与0节点(power plant)相连的MST边是不会出故障的,所以要特殊考虑一下所有MST边都跟0节点相连的情况。

删除MST中某条边后的次小生成树用树形dp解决,传送门

我的理解是:删除MST边<u, v>之后, MST被划分成u跟v两个子树,新添加的非MST边必然是连接u跟v两颗子树的原图中的非MST边,这可以用dfs解决。dp[u][v]代表两颗子树的最短距离,用每个点p的非MST边g[p][i]去更新所有的dp[u][v],时间复杂度O(n^2)。

[cpp]  view plain copy
  1. //#pragma comment(linker, "/STACK:1024000000,1024000000")  
  2. #include<algorithm>  
  3. #include<iostream>  
  4. #include<cstring>  
  5. #include<fstream>  
  6. #include<sstream>  
  7. #include<vector>  
  8. #include<string>  
  9. #include<cstdio>  
  10. #include<bitset>  
  11. #include<queue>  
  12. #include<stack>  
  13. #include<cmath>  
  14. #include<map>  
  15. #include<set>  
  16. #define FF(i, a, b) for(int i=a; i<b; i++)  
  17. #define FD(i, a, b) for(int i=a; i>=b; i--)  
  18. #define REP(i, n) for(int i=0; i<n; i++)  
  19. #define CLR(a, b) memset(a, b, sizeof(a))  
  20. #define debug puts("**debug**")  
  21. #define LL long long  
  22. #define PB push_back  
  23. #define MP make_pair  
  24. #define eps 1e-10  
  25. using namespace std;  
  26.   
  27. const int maxn = 1010;  
  28. const double INF = 1e20;  
  29. int n, T, fa[maxn];  
  30. double mst, k, x[maxn], y[maxn], g[maxn][maxn], dp[maxn][maxn], d[maxn];  
  31. bool vis[maxn];  
  32. vector<int> G[maxn];  
  33.   
  34. template <class T> T sqr(T x) { return x*x; }  
  35. double dist(int i, int j)  
  36. {  
  37.     return sqrt(sqr(x[i]-x[j]) + sqr(y[i] - y[j]));  
  38. }  
  39.   
  40. void read()  
  41. {  
  42.     scanf("%d%lf", &n, &k);  
  43.     REP(i, n) scanf("%lf%lf", &x[i], &y[i]);  
  44.     REP(i, n)  
  45.     {  
  46.         FF(j, i+1, n) g[i][j] = g[j][i] = dist(i, j), dp[i][j] = dp[j][i] = INF;  
  47.         g[i][i] = INF;  
  48.         vis[i] = 0;  
  49.         fa[i] = 0;  
  50.         G[i].clear();  
  51.     }  
  52. }  
  53.   
  54. void prim()  
  55. {  
  56.     REP(i, n) d[i] = g[0][i];  
  57.     vis[0] = 1;  
  58.     fa[0] = -1;  
  59.     d[0] = INF;  
  60.     mst = 0;  
  61.     FF(i, 1, n)  
  62.     {  
  63.         int pos = 0;  
  64.         FF(j, 1, n) if(!vis[j] && d[pos] > d[j]) pos = j;  
  65.   
  66.         mst += d[pos];  
  67.         vis[pos] = 1;  
  68.   
  69.         //构造MST  
  70.         G[pos].PB(fa[pos]);  
  71.         G[fa[pos]].PB(pos);  
  72.   
  73.         FF(j, 1, n) if(!vis[j] && g[pos][j] < d[j])  
  74.             d[j] = g[pos][j], fa[j] = pos;  
  75.     }  
  76. }  
  77.   
  78. //用所有非MST边g[p][i] 更新所有dp[u][v]  
  79. double dfs(int p, int u, int f)  
  80. {  
  81.     double ans = INF;  
  82.     REP(i, G[u].size())  
  83.     {  
  84.         int v = G[u][i];  
  85.         if(v != f)  
  86.         {  
  87.             double tmp = dfs(p, v, u);  
  88.             ans = min(ans, tmp);  
  89.             dp[u][v] = dp[v][u] = min(dp[u][v], tmp);  
  90.         }  
  91.     }  
  92.     //保证非MST边才能更新  
  93.     if(p != f) ans = min(ans, g[p][u]);  
  94.     return ans;  
  95. }  
  96.   
  97. double solve()  
  98. {  
  99.     REP(i, n) dfs(i, i, -1); //每个点更新一次  
  100.   
  101.     //MST中所有跟0节点相连的边是不会出问题的  
  102.     bool flag = 0;  
  103.     FF(i, 1, n) if(fa[0] != i && fa[i] != 0) flag = 1;  
  104.     if(!flag) return mst * k;  
  105.   
  106.     double ret = 0;  
  107.     //求MST边删除后的次小生成树的最大值  
  108.     FF(i, 1, n) FF(j, i+1, n) if(fa[i] == j || fa[j] == i)ret = max(ret, dp[i][j] - g[i][j]);  
  109.     return (mst + ret) * k;  
  110. }  
  111.   
  112. int main()  
  113. {  
  114.     scanf("%d", &T);  
  115.     while(T--)  
  116.     {  
  117.         read();  
  118.         prim();  
  119.         printf("%.2lf\n", solve());  
  120.     }  
  121.     return 0;  
  122. }  

 

hdu 4756 Install Air Conditioning(2013南京网络赛)

分类: dp   303人阅读  评论(4)  收藏  举报

题意就是求MST中删去一条边后,次小生成树最大的那颗。注意题中说了“ there are so many wires between two specific dormitories” 。也就是说与0节点(power plant)相连的MST边是不会出故障的,所以要特殊考虑一下所有MST边都跟0节点相连的情况。

删除MST中某条边后的次小生成树用树形dp解决,传送门

我的理解是:删除MST边<u, v>之后, MST被划分成u跟v两个子树,新添加的非MST边必然是连接u跟v两颗子树的原图中的非MST边,这可以用dfs解决。dp[u][v]代表两颗子树的最短距离,用每个点p的非MST边g[p][i]去更新所有的dp[u][v],时间复杂度O(n^2)。

[cpp]  view plain copy
  1. //#pragma comment(linker, "/STACK:1024000000,1024000000")  
  2. #include<algorithm>  
  3. #include<iostream>  
  4. #include<cstring>  
  5. #include<fstream>  
  6. #include<sstream>  
  7. #include<vector>  
  8. #include<string>  
  9. #include<cstdio>  
  10. #include<bitset>  
  11. #include<queue>  
  12. #include<stack>  
  13. #include<cmath>  
  14. #include<map>  
  15. #include<set>  
  16. #define FF(i, a, b) for(int i=a; i<b; i++)  
  17. #define FD(i, a, b) for(int i=a; i>=b; i--)  
  18. #define REP(i, n) for(int i=0; i<n; i++)  
  19. #define CLR(a, b) memset(a, b, sizeof(a))  
  20. #define debug puts("**debug**")  
  21. #define LL long long  
  22. #define PB push_back  
  23. #define MP make_pair  
  24. #define eps 1e-10  
  25. using namespace std;  
  26.   
  27. const int maxn = 1010;  
  28. const double INF = 1e20;  
  29. int n, T, fa[maxn];  
  30. double mst, k, x[maxn], y[maxn], g[maxn][maxn], dp[maxn][maxn], d[maxn];  
  31. bool vis[maxn];  
  32. vector<int> G[maxn];  
  33.   
  34. template <class T> T sqr(T x) { return x*x; }  
  35. double dist(int i, int j)  
  36. {  
  37.     return sqrt(sqr(x[i]-x[j]) + sqr(y[i] - y[j]));  
  38. }  
  39.   
  40. void read()  
  41. {  
  42.     scanf("%d%lf", &n, &k);  
  43.     REP(i, n) scanf("%lf%lf", &x[i], &y[i]);  
  44.     REP(i, n)  
  45.     {  
  46.         FF(j, i+1, n) g[i][j] = g[j][i] = dist(i, j), dp[i][j] = dp[j][i] = INF;  
  47.         g[i][i] = INF;  
  48.         vis[i] = 0;  
  49.         fa[i] = 0;  
  50.         G[i].clear();  
  51.     }  
  52. }  
  53.   
  54. void prim()  
  55. {  
  56.     REP(i, n) d[i] = g[0][i];  
  57.     vis[0] = 1;  
  58.     fa[0] = -1;  
  59.     d[0] = INF;  
  60.     mst = 0;  
  61.     FF(i, 1, n)  
  62.     {  
  63.         int pos = 0;  
  64.         FF(j, 1, n) if(!vis[j] && d[pos] > d[j]) pos = j;  
  65.   
  66.         mst += d[pos];  
  67.         vis[pos] = 1;  
  68.   
  69.         //构造MST  
  70.         G[pos].PB(fa[pos]);  
  71.         G[fa[pos]].PB(pos);  
  72.   
  73.         FF(j, 1, n) if(!vis[j] && g[pos][j] < d[j])  
  74.             d[j] = g[pos][j], fa[j] = pos;  
  75.     }  
  76. }  
  77.   
  78. //用所有非MST边g[p][i] 更新所有dp[u][v]  
  79. double dfs(int p, int u, int f)  
  80. {  
  81.     double ans = INF;  
  82.     REP(i, G[u].size())  
  83.     {  
  84.         int v = G[u][i];  
  85.         if(v != f)  
  86.         {  
  87.             double tmp = dfs(p, v, u);  
  88.             ans = min(ans, tmp);  
  89.             dp[u][v] = dp[v][u] = min(dp[u][v], tmp);  
  90.         }  
  91.     }  
  92.     //保证非MST边才能更新  
  93.     if(p != f) ans = min(ans, g[p][u]);  
  94.     return ans;  
  95. }  
  96.   
  97. double solve()  
  98. {  
  99.     REP(i, n) dfs(i, i, -1); //每个点更新一次  
  100.   
  101.     //MST中所有跟0节点相连的边是不会出问题的  
  102.     bool flag = 0;  
  103.     FF(i, 1, n) if(fa[0] != i && fa[i] != 0) flag = 1;  
  104.     if(!flag) return mst * k;  
  105.   
  106.     double ret = 0;  
  107.     //求MST边删除后的次小生成树的最大值  
  108.     FF(i, 1, n) FF(j, i+1, n) if(fa[i] == j || fa[j] == i)ret = max(ret, dp[i][j] - g[i][j]);  
  109.     return (mst + ret) * k;  
  110. }  
  111.   
  112. int main()  
  113. {  
  114.     scanf("%d", &T);  
  115.     while(T--)  
  116.     {  
  117.         read();  
  118.         prim();  
  119.         printf("%.2lf\n", solve());  
  120.     }  
  121.     return 0;  
  122. }  

图论专题训练1-C(最短路和次短路问题,dijkstra算法)

分类: 算法题解-图论 算法题解-图论-最短路径   109人阅读  评论(0)  收藏  举报
ACM 算法 dijkstra

题目链接

[cpp]  view plain copy print ?
  1. /* 
  2.  *题目大意: 
  3.  *在一个有向图中,求从s到t两个点之间的最短路和比最短路长1的次短路的条数之和; 
  4.  * 
  5.  *算法思想: 
  6.  *用A*求第K短路,目测会超时,直接在dijkstra算法上求次短路; 
  7.  *将dist数组开成二维的,即dist[v][2],第二维分别用于记录最短路和次短路; 
  8.  *再用一个cnt二维数组分别记录最短路和次短路的条数; 
  9.  *每次更新路径的条数时,不能直接加1,,应该加上cnt[u][k],k为次短路径或者最短路径的标记; 
  10.  *图有重边,不能用邻接矩阵存储; 
  11.  *不知道为什么,题目上说的是N and M, separated by a single space, with 2≤N≤1000 and 1 ≤ M ≤ 10000; 
  12.  *而我的代码硬是把N开成1W了才过,求解释,RE了无数次,擦; 
  13. **/  
  14. #include<iostream>  
  15. #include<cstdio>  
  16. #include<cstring>  
  17. #include<string>  
  18. #include<algorithm>  
  19. using namespace std;  
  20.   
  21. const int N=11111;  
  22. const int M=111111;  
  23. const int INF=0xffffff;  
  24.   
  25. struct node  
  26. {  
  27.     int to;  
  28.     int w;  
  29.     int next;  
  30. };  
  31.   
  32. node edge[N];  
  33. int head[N];  
  34.   
  35. int dist[N][2],cnt[N][2];  
  36. bool vis[N][2];  
  37. int n,m,s,t,edges;  
  38.   
  39. void addedge(int u,int v,int w)  
  40. {  
  41.     edge[edges].w=w;  
  42.     edge[edges].to=v;  
  43.     edge[edges].next=head[u];  
  44.     head[u]=edges++;  
  45. }  
  46.   
  47. int dijkstra()  
  48. {  
  49.     int k;  
  50.     for(int i=0; i<=n; i++)  
  51.     {  
  52.         dist[i][0]=dist[i][1]=INF;  
  53.         vis[i][0]=vis[i][1]=0;  
  54.         cnt[i][0]=cnt[i][1]=0;  
  55.     }  
  56.     cnt[s][0]=1,dist[s][0]=0;  
  57.   
  58.     for(int i=1; i<=n*2; i++)  
  59.     {  
  60.         int u=-1;  
  61.         int min_dist=INF;  
  62.         for(int j=1; j<=n; j++)  
  63.             for(int flag=0; flag<2; flag++)  
  64.                 if(!vis[j][flag]&&dist[j][flag]<min_dist)  
  65.                 {  
  66.                     min_dist=dist[j][flag];  
  67.                     u=j;  
  68.                     k=flag;  
  69.                 }  
  70.         if(u==-1)  
  71.             break;  
  72.         vis[u][k]=true;  
  73.         for(int e=head[u]; e!=-1; e=edge[e].next)  
  74.         {  
  75.             int j=edge[e].to;  
  76.             int tmp=dist[u][k]+edge[e].w;  
  77.   
  78.             if(tmp<dist[j][0])//tmp小于最短路径长:  
  79.             {  
  80.                 dist[j][1]=dist[j][0];//次短路径长  
  81.                 cnt[j][1]=cnt[j][0];//次短路径计数  
  82.                 dist[j][0]=tmp;//最短路径长  
  83.                 cnt[j][0]=cnt[u][k];//最短路径计数  
  84.             }  
  85.   
  86.             else if(tmp==dist[j][0])//tmp等于最短路径长:  
  87.             {  
  88.                 cnt[j][0]+=cnt[u][k];//最短路径计数  
  89.             }  
  90.   
  91.             else if(tmp<dist[j][1])//tmp大于最短路径长且小于次短路径长:  
  92.             {  
  93.                 dist[j][1]=tmp;//次短路径长  
  94.                 cnt[j][1]=cnt[u][k];//次短路径计数  
  95.             }  
  96.   
  97.             else if(tmp==dist[j][1])//tmp等于次短路径长:  
  98.             {  
  99.                 cnt[j][1]+=cnt[u][k];//次短路径计数  
  100.             }  
  101.         }  
  102.     }  
  103.   
  104.     int res=cnt[t][0];  
  105.     if(dist[t][0]+1==dist[t][1])//判断最短路和次短路是否相差1  
  106.         res+=cnt[t][1];  
  107.     return res;  
  108. }  
  109.   
  110. int main()  
  111. {  
  112.     //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);  
  113.     int tcase;  
  114.     scanf("%d",&tcase);  
  115.     while(tcase--)  
  116.     {  
  117.         edges=0;  
  118.         scanf("%d%d",&n,&m);  
  119.         memset(head,-1,sizeof(head));  
  120.         int u,v,w;  
  121.         for(int i=0; i<m; i++)  
  122.         {  
  123.             scanf("%d%d%d",&u,&v,&w);  
  124.             addedge(u,v,w);  
  125.         }  
  126.         scanf("%d%d",&s,&t);  
  127.         printf("%d\n",dijkstra());  
  128.     }  
  129.     return 0;  
  130. }  


你可能感兴趣的:(dp,dp,MST,算法题解-图论,算法题解-图论-最短路径)