求一个图最短路边的办法。好像下面的那个有问题。单向边和双向边一定是有区别的。这个比较容易。参照该文的最短路网络流题目和连通图题目一题求最短路关节边

另外上述2个题目的代码好像有问题。

在UVALIVE 6885中不能得到AC。不知道原因。感觉是对的。

另一种判断最短路的方法就是

从起点到u+从终点到v+边U,V权值==最短路值那么这条边为最短路

这种方案的代码

  1. for (int i = ; i <= M ; i++) {
  2. scanf("%d%d%d",&u[i],&v[i],&w[i]);
  3. u[i]++;v[i]++;
  4. S.add_edge(u[i],v[i],w[i],i);
  5. S.add_edge(v[i],u[i],w[i],i);
  6. T.add_edge(u[i],v[i],w[i],i);
  7. T.add_edge(v[i],u[i],w[i],i);
  8. }
  9. S.dijkstra(source);
  10. T.dijkstra(target);
  11. long long ans = ;
  12. for (int i = ; i <= P ; i++) {
  13. for (int j = S.head[i] ; j != - ; j = S.edge[j].next) {
  14. int v = S.edge[j].v;
  15. if (S.dis[i] + T.dis[v] + S.edge[j].w == S.dis[target])
  16. //这条边为最短路边
  17. }
  18. }

同时另一种可能存在问题的方法如下

  1. for (int i = ; i <= m ; i++)
  2. {
  3. scanf("%d%d%I64d",&u[i],&v[i],&w[i]);
  4. S.add_edge(u[i],v[i],w[i],i);
  5. S.add_edge(v[i],u[i],w[i],i);
  6. T.add_edge(u[i],v[i],w[i],i);
  7. T.add_edge(v[i],u[i],w[i],i);
  8. }
  9. S.dijkstra(s);
  10. T.dijkstra(t);
  11. init();
  12. for (int i = ; i <= m ; i++)
  13. {
  14. int tu = u[i];
  15. int tv = v[i];
  16. LL tw = w[i];
  17. if ((S.dis[tu] + tw == S.dis[tv] && T.dis[tv] + tw == T.dis[tu])
  18. ||(S.dis[tv] + tw == S.dis[tu] && T.dis[tu] + tw == T.dis[tv]))
  19. {
  20. add_edge(tu,tv,tw,i);
  21. add_edge(tv,tu,tw,i);//这里是为了处理tarjan无向图 其实就是u[i],v[i],w[i]这条边为最短路边。
  22. }
  23. }
  24. slove(n);

对于上述方案的有向图 建图有区别

如下

  1. for (int i = ; i < M ; i++)
  2. {
  3. scanf("%d%d%d",&u[i],&v[i],&w[i]);
  4. St.add_edge(u[i],v[i],w[i],i + );
  5. //St.add_edge(v[i],u[i],w[i],i + 1);
  6. //Ted.add_edge(u[i],v[i],w[i],i + 1);
  7. Ted.add_edge(v[i],u[i],w[i],i + );
  8. }
  9. scanf("%d%d",&A,&B);
  10. St.dijkstra(A);
  11. /* if (St.dis[B] == INF)
  12. {
  13. puts("0");
  14. continue;
  15. }
  16. */
  17. Ted.dijkstra(B);
  18. for (int i = ; i < M ; i++)
  19. {
  20. int tu = u[i];
  21. int tv = v[i];
  22. int tw = w[i];
  23. if (tu == tv) continue;
  24. if ((St.dis[tu] + tw == St.dis[tv] && Ted.dis[tv] + tw == Ted.dis[tu])
  25. ||(St.dis[tv] + tw == St.dis[tu] && Ted.dis[tu] + tw == Ted.dis[tv]))
  26. {
  27. add_edge(tu,tv,);//这里添加的是网络流的边无需双向
  28. }
  29. }

POJ 2387 Til the Cows Come Home

直接求最短路末班题。我这里是dijkstra+优先队列优化的班

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const int INF = 0x3f3f3f3f;
  25. struct Edge
  26. {
  27. int u,v,next;
  28. int w;
  29. }edge[MAXM];
  30. int head[MAXN],tot;
  31.  
  32. void init()
  33. {
  34. tot = ;
  35. memset(head,-,sizeof(head));
  36. }
  37.  
  38. void add_edge(int u,int v,int w)
  39. {
  40. edge[tot].u = u;
  41. edge[tot].v = v;
  42. edge[tot].w = w;
  43. edge[tot].next = head[u];
  44. head[u] = tot++;
  45. }
  46.  
  47. struct heapnode
  48. {
  49. int val,u;
  50. bool operator < (const heapnode &rhs) const
  51. {
  52. return val > rhs.val;
  53. }
  54. };
  55.  
  56. bool done[MAXN];
  57. int dis[MAXN];
  58. priority_queue<heapnode>q;
  59. int N,M;
  60.  
  61. void dijkstra(int s)
  62. {
  63. memset(done,false,sizeof(done));
  64. while (!q.empty()) q.pop();
  65. memset(dis,0x3f,sizeof(dis));
  66. dis[s] = ;
  67. q.push((heapnode){dis[s],s});
  68. while (!q.empty())
  69. {
  70. heapnode x = q.top(); q.pop();
  71. int u = x.u;
  72. if (done[u]) continue;
  73. done[u] = true;
  74. for (int i = head[u] ; i != - ; i = edge[i].next)
  75. {
  76. int v = edge[i].v;
  77. if (dis[v] > dis[u] + edge[i].w)
  78. {
  79. dis[v] = dis[u] + edge[i].w;
  80. q.push((heapnode){dis[v],v});
  81. }
  82. }
  83. }
  84. }
  85.  
  86. int main()
  87. {
  88. while (scanf("%d%d",&N,&M) != EOF)
  89. {
  90. swap(N,M);
  91. init();
  92. for (int i = ; i < M ; i++)
  93. {
  94. int u,v,w;
  95. scanf("%d%d%d",&u,&v,&w);
  96. add_edge(u,v,w);
  97. add_edge(v,u,w);
  98. }
  99. dijkstra();
  100. printf("%d\n",dis[N]);
  101. }
  102. return ;
  103. }

POJ 2253 Frogger

从1号点跳到2号点所经过的路径中最短的路径长度

可以用类似最小生成树的思路来解

这里用的kruskal

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = MAXN * MAXN;
  24. struct Edge
  25. {
  26. int u,v;
  27. double w;
  28. friend bool operator <(const Edge &a,const Edge &b)
  29. {
  30. return a.w < b.w;
  31. }
  32. }edge[MAXM];
  33. int fa[MAXN],tot,N;
  34. double x[MAXN],y[MAXN];
  35. int Find(int x) {return x == fa[x] ? x : fa[x] = Find(fa[x]);}
  36.  
  37. bool judge()
  38. {
  39. int fu = Find();
  40. int fv = Find();
  41. if(fu == fv) return true;
  42. return false;
  43. }
  44.  
  45. void build()
  46. {
  47. tot = ;
  48. for (int i = ; i <= N ; i++)scanf("%lf%lf",&x[i],&y[i]);
  49. for (int i = ; i <= N ; i++)
  50. {
  51. for (int j = i + ; j <= N ; j++)
  52. {
  53. double dis = sqrt((x[i] - x[j]) * (x[i] - x[j]) +
  54. (y[i] - y[j]) * (y[i] - y[j]));
  55. edge[tot].u = i;
  56. edge[tot].v = j;
  57. edge[tot].w = dis;
  58. tot++;
  59. }
  60. }
  61. }
  62.  
  63. double kruskal()
  64. {
  65. int cnt = ;
  66. double ret = 0.0;
  67. sort(edge,edge + tot);
  68. for (int i = ; i <= N ; i++) fa[i] = i;
  69. for (int i = ; i < tot ; i++)
  70. {
  71. if (judge()) return ret;
  72. int fu = Find(edge[i].u);
  73. int fv = Find(edge[i].v);
  74. if (fu != fv)
  75. {
  76. fa[fu] = fv;
  77. cnt++;
  78. ret = max(ret,edge[i].w);
  79. }
  80. }
  81. return ret;
  82. }
  83.  
  84. int main()
  85. {
  86. //freopen("sample.txt","r",stdin);
  87. int kase = ;
  88. while (scanf("%d",&N) != EOF)
  89. {
  90. if (N == ) break;
  91. printf("Scenario #%d\nFrog Distance = ",kase++);
  92. build();
  93. printf("%.3f\n",kruskal());
  94. putchar('\n');
  95. }
  96. return ;
  97. }

另一种建立在理解dijkstra的基础上的代码。根据题意来确定相关更新

实际上这套题最困扰我的就是这几个dijkstra思想的题目。太弱。。

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const double INF = 1e12;
  25. struct node
  26. {
  27. double x,y;
  28. }src[MAXN];
  29. double dis[MAXN];
  30. bool vis[MAXN];
  31. int N;
  32.  
  33. double dist(node a,node b)
  34. {
  35. return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
  36. }
  37.  
  38. void dijkstra()
  39. {
  40. memset(vis,false,sizeof(vis));
  41. for (int i = ; i < MAXN ; i++) dis[i] = INF * 1.0;
  42. dis[] = 0.0;
  43. for (int i = ; i <= N ; i++)
  44. {
  45. double mincost = INF;
  46. int pos = - ;
  47. for (int j = ; j <= N ; j++)
  48. {
  49. if (!vis[j] && dis[j] < mincost)
  50. {
  51. mincost = dis[j];
  52. pos = j;
  53. }
  54. }
  55. if (pos == -) return;
  56. vis[pos] = true;
  57. if (pos == ) return;
  58. for (int j = ; j <= N ; j++)
  59. {
  60. if (!vis[j] && dis[j] > max(dis[pos],dist(src[pos],src[j])))
  61. dis[j] = max(dis[pos],dist(src[pos],src[j]));
  62. }
  63. }
  64. }
  65.  
  66. int main()
  67. {
  68. int kase = ;
  69. while (scanf("%d",&N) != EOF)
  70. {
  71. if (N == ) break;
  72. for (int i = ; i <= N ; i++) scanf("%lf%lf",&src[i].x,&src[i].y);
  73. dijkstra();
  74. printf("Scenario #%d\nFrog Distance = %.3f\n\n",kase++,dis[]);
  75. }
  76. return ;
  77. }

POJ 1797 Heavy Transportation

一号点到N号点的合法路径中最小的边的最大值 ,这个实际就是最大生成树。直接kruskal很容易

这里还是要用下dijkstra和prim来区分一下。

下面这里是别人博客的一段话

在图论中,Prim算法是计算最小生成树的算法,而Dijkstra算法是计算最短路径的算法。二者看起来比较类似,因为假设全部顶点的集合是V,已经被挑选出来的点的集合是U,那么二者都是从集合V-U中不断的挑选权值最低的点加入U,那么二者是否等价呢?也就是说是否Dijkstra也可以计算出最小生成树而Prim也可以计算出从第一个顶点v0到其他点的最短路径呢?答案是否定的,否则就不必有两个算法了。

二者的不同之处在于“权值最低”的定义不同,Prim的“权值最低”是相对于U中的任意一点而言的,也就是把U中的点看成一个整体,每次寻找V-U中跟U的距离最小(也就是跟U中任意一点的距离最小)的一点加入U;而Dijkstra的“权值最低”是相对于v0而言的,也就是每次寻找V-U中跟v0的距离最小的一点加入U。

一个可以说明二者不等价的例子是有四个顶点(v0, v1, v2, v3)和四条边且边值定义为(v0, v1)=20, (v0, v2)=10, (v1, v3)=2, (v3, v2)=15的图,用Prim算法得到的最小生成树中v0跟v1是不直接相连的,也就是在最小生成树中v0v1的距离是v0->v2->v3->v1的距离是27,而用Dijkstra算法得到的v0v1的距离是20,也就是二者直接连线的长度。

第一份是dijkstra的

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. int dis[MAXN][MAXN];
  24. int N,M;
  25. bool vis[MAXN];
  26. int d[MAXN];
  27.  
  28. void dijkstra()
  29. {
  30. memset(vis,false,sizeof(vis));
  31. memset(d,,sizeof(d));
  32. for (int i = ; i <= N ; i++) d[i] = dis[][i];
  33. for (int i = ; i <= N ; i++)
  34. {
  35. int maxcost = - ;
  36. int pos = -;
  37. for (int j = ; j <= N ; j++)
  38. {
  39. if (!vis[j] && d[j] > maxcost)
  40. {
  41. maxcost = d[j];
  42. pos = j;
  43. }
  44. }
  45. if (pos == -) return;
  46. if (pos == N) return;
  47. vis[pos] = true;
  48. for (int j = ; j <= N ; j++)
  49. {
  50. if (!vis[j] && d[j] < min(d[pos],dis[pos][j]))
  51. d[j] = min(d[pos],dis[pos][j]);
  52. }
  53. }
  54. }
  55.  
  56. int main()
  57. {
  58. int kase = ;
  59. int T;
  60. scanf("%d",&T);
  61. while (T--)
  62. {
  63. scanf("%d%d",&N,&M);
  64. memset(dis,,sizeof(dis));
  65. for (int i = ; i < M ; i++)
  66. {
  67. int u,v,w;
  68. scanf("%d%d%d",&u,&v,&w);
  69. dis[u][v] = dis[v][u] = w;
  70. }
  71. printf("Scenario #%d:\n",kase++);
  72. dijkstra();
  73. printf("%d\n\n",d[N]);
  74. }
  75. return ;
  76. }

第二份是prim的。仔细比对就发现差异

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int INF = 0x3f3f3f3f;
  24. int dis[MAXN][MAXN];
  25. int N,M,ans;
  26. bool vis[MAXN];
  27. int d[MAXN];
  28.  
  29. void dijkstra()
  30. {
  31. memset(vis,false,sizeof(vis));
  32. memset(d,,sizeof(d));
  33. for (int i = ; i <= N ; i++) d[i] = dis[][i];
  34. d[] = ;
  35. vis[] = true;
  36. ans = INF;
  37. for (int i = ; i <= N ; i++)
  38. {
  39. int maxcost = - ;
  40. int pos = -;
  41. for (int j = ; j <= N ; j++)
  42. {
  43. if (!vis[j] && d[j] > maxcost)
  44. {
  45. maxcost = d[j];
  46. pos = j;
  47. }
  48. }
  49. if (pos == -) return;
  50. ans = min(ans,maxcost);
  51. if (pos == N) return;
  52. vis[pos] = true;
  53. for (int j = ; j <= N ; j++)
  54. {
  55. if (!vis[j] && d[j] < dis[pos][j])
  56. d[j] = dis[pos][j];
  57. }
  58. }
  59. }
  60.  
  61. int main()
  62. {
  63. int kase = ;
  64. int T;
  65. scanf("%d",&T);
  66. while (T--)
  67. {
  68. scanf("%d%d",&N,&M);
  69. memset(dis,,sizeof(dis));
  70. for (int i = ; i < M ; i++)
  71. {
  72. int u,v,w;
  73. scanf("%d%d%d",&u,&v,&w);
  74. dis[u][v] = dis[v][u] = w;
  75. }
  76. printf("Scenario #%d:\n",kase++);
  77. dijkstra();
  78. printf("%d\n\n",ans);
  79. }
  80. return ;
  81. }

POJ 3268 Silver Cow Party

有向图中从所有点到A点,再所有点从A点回到原本位置,问其中这些路径中最长的是哪个。

所有点从A回到原点是一次单元最短路即可。另一半怎么做。建反图,再从A求一次最短路,详情代码

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const LL INF = 0x3f3f3f3f;
  25. struct Edge
  26. {
  27. int u,v,next;
  28. LL w;
  29. }edge[MAXM],res[MAXN];
  30. int head[MAXN],tot;
  31. int N,M,X;
  32.  
  33. void init()
  34. {
  35. memset(head,-,sizeof(head));
  36. tot = ;
  37. }
  38.  
  39. void add_edge(int u,int v,LL w)
  40. {
  41. edge[tot].u = u;
  42. edge[tot].v = v;
  43. edge[tot].w = w;
  44. edge[tot].next = head[u];
  45. head[u] = tot++;
  46. }
  47.  
  48. bool done[MAXN];
  49. LL dis[][MAXN];
  50. struct heapnode
  51. {
  52. LL val;
  53. int u;
  54. bool operator < (const heapnode &rhs) const
  55. {
  56. return val > rhs.val;
  57. }
  58. };
  59.  
  60. void dijkstra(int s,int id)
  61. {
  62. memset(dis[id],0x3f,sizeof(dis[id]));
  63. memset(done,false,sizeof(done));
  64. priority_queue<heapnode>q;
  65. dis[id][s] = ;
  66. q.push((heapnode){dis[id][s],s});
  67. while (!q.empty())
  68. {
  69. heapnode x = q.top(); q.pop();
  70. int u = x.u;
  71. //printf("%d %d\n",u,dis[id][u]);
  72. if (done[u]) continue;
  73. done[u] = true;
  74. for (int i = head[u] ; i != - ; i = edge[i].next)
  75. {
  76. int v = edge[i].v;
  77. if (dis[id][v] > dis[id][u] + edge[i].w)
  78. {
  79. dis[id][v] = dis[id][u] + edge[i].w;
  80. q.push((heapnode){dis[id][v],v});
  81. }
  82. }
  83. }
  84. }
  85.  
  86. void slove()
  87. {
  88. //memset(dis,0x3f,sizeof(dis));
  89. for (int i = ; i < M ; i++)
  90. {
  91. scanf("%d%d%I64d",&res[i].u,&res[i].v,&res[i].w);
  92. }
  93. init();
  94. for (int i = ; i < M ; i++)
  95. add_edge(res[i].u,res[i].v,res[i].w);
  96. dijkstra(X,);
  97. init();
  98. for (int i = ; i < M ; i++)
  99. add_edge(res[i].v,res[i].u,res[i].w);
  100. dijkstra(X,);
  101. LL ret = ;
  102. for (int i = ; i <= N ; i++)
  103. {
  104. if (i == X || dis[][i] == INF || dis[][i] == INF) continue;
  105. ret = max(ret,dis[][i] + dis[][i]);
  106. }
  107. printf("%I64d\n",ret);
  108. }
  109.  
  110. int main()
  111. {
  112. while (scanf("%d%d%d",&N,&M,&X) != EOF)
  113. {
  114. slove();
  115. }
  116. return ;
  117. }

POJ 1860 Currency Exchange
如何判断正环。这里2分代码。第一份spfa

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. struct Edge
  25. {
  26. int u,v,next;
  27. double rate,commission;
  28. }edge[MAXM];
  29. int head[MAXN],tot;
  30. int N,M,S;
  31. double val;
  32.  
  33. void init()
  34. {
  35. memset(head,-,sizeof(head));
  36. tot = ;
  37. }
  38.  
  39. void add_edge(int u,int v,double rate,double commission)
  40. {
  41. edge[tot].u = u;
  42. edge[tot].v = v;
  43. edge[tot].rate = rate;
  44. edge[tot].commission = commission;
  45. edge[tot].next = head[u];
  46. head[u] = tot++;
  47. }
  48.  
  49. double dis[MAXN];
  50. bool inq[MAXN];
  51. int cnt[MAXN];
  52. queue<int>q;
  53. bool spfa(int s)
  54. {
  55. while (!q.empty()) q.pop();
  56. for (int i = ; i <= N ; i++) dis[i] = -;
  57. memset(inq,false,sizeof(inq));
  58. memset(cnt,,sizeof(cnt));
  59. q.push(s);
  60. dis[s] = val;
  61. inq[s] = true;
  62. cnt[s] = ;
  63. while (!q.empty())
  64. {
  65. int u = q.front(); q.pop();
  66. inq[u] = false;
  67. for (int i = head[u] ; i != - ; i = edge[i].next)
  68. {
  69. int v = edge[i].v;
  70. double rate = edge[i].rate;
  71. double commission = edge[i].commission;
  72. double price = (dis[u] - commission) * rate;
  73. if (price > dis[v])
  74. {
  75. dis[v] = price;
  76. if (!inq[v])
  77. {
  78. q.push(v);
  79. cnt[v]++;
  80. inq[v] = true;
  81. }
  82. if (cnt[v] >= N) return true;
  83. }
  84. }
  85. if (dis[S] > val) return true;
  86. }
  87. return false;
  88. }
  89.  
  90. int main()
  91. {
  92. while (scanf("%d%d%d%lf",&N,&M,&S,&val) != EOF)
  93. {
  94. init();
  95. for (int i = ; i < M ; i++)
  96. {
  97. int a,b;
  98. double rab,cab,rba,cba;
  99. scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
  100. add_edge(a,b,rab,cab);
  101. add_edge(b,a,rba,cba);
  102. }
  103. bool flag = spfa(S);
  104. if (flag) puts("YES");
  105. else printf("NO\n");
  106. }
  107. return ;
  108. }

第二份bellman_ford
注意迭代的次数为N-1,判断是否还正环和原本的一样、枚举边来松弛

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. int N,M,S;
  25. double val;
  26. int tot;
  27. double dis[MAXN];
  28. struct Edge
  29. {
  30. int u,v;
  31. double r,c;
  32. }edge[MAXM];
  33.  
  34. bool bellman_ford()
  35. {
  36. memset(dis,,sizeof(dis));
  37. dis[S] = val;
  38. bool flag;
  39. for (int i = ; i <= N - ; i++)
  40. {
  41. flag = false;
  42. for (int j = ; j < tot ; j++)
  43. {
  44. if (dis[edge[j].v] < (dis[edge[j].u] - edge[j].c) * edge[j].r)
  45. {
  46. dis[edge[j].v] = (dis[edge[j].u] - edge[j].c) * edge[j].r;
  47. flag = true;
  48. }
  49. }
  50. if (!flag) break;
  51. }
  52.  
  53. for (int i = ; i < tot ; i++)
  54. {
  55. if (dis[edge[i].v] < (dis[edge[i].u] - edge[i].c) * edge[i].r)
  56. return true;
  57. }
  58. return false;
  59. }
  60.  
  61. int main()
  62. {
  63. while (cin >> N >> M >> S >> val)
  64. {
  65. tot = ;
  66. for (int i = ; i < M ; i++)
  67. {
  68. int a,b;
  69. double rab,cab,rba,cba;
  70. cin >> a >> b >> rab >> cab >> rba >> cba;
  71. edge[tot].u = a;
  72. edge[tot].v = b;
  73. edge[tot].r = rab;
  74. edge[tot].c = cab;
  75. tot++;
  76. edge[tot].u = b;
  77. edge[tot].v = a;
  78. edge[tot].r = rba;
  79. edge[tot].c = cba;
  80. tot++;
  81. }
  82. if (bellman_ford()) puts("YES");
  83. else puts("NO");
  84. }
  85. return ;
  86.  
  87. }

POJ 3259 Wormholes

判负环 同样2种代码

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const int INF = 0x3f3f3f3f;
  25. struct Edge
  26. {
  27. int u,v,w;
  28. int next;
  29. }edge[MAXM];
  30. int head[MAXN],tot;
  31. int N,M,W;
  32.  
  33. void init()
  34. {
  35. memset(head,-,sizeof(head));
  36. tot = ;
  37. }
  38.  
  39. void add_edge(int u,int v,int w)
  40. {
  41. edge[tot].u = u;
  42. edge[tot].v = v;
  43. edge[tot].w = w;
  44. edge[tot].next = head[u];
  45. head[u] = tot++;
  46. }
  47.  
  48. bool inq[MAXN];
  49. queue<int>q;
  50. int cnt[MAXN];
  51. int dis[MAXN];
  52. bool SPFA()
  53. {
  54. while (!q.empty()) q.pop();
  55. for (int i = ; i <= N ; i++)
  56. {
  57. dis[i] = INF;
  58. q.push(i);
  59. cnt[i] = ;
  60. inq[i] = true;
  61. }
  62. while (!q.empty())
  63. {
  64. int u = q.front(); q.pop();
  65. inq[u] = false;
  66. for (int i = head[u] ; i != - ; i = edge[i].next)
  67. {
  68. int v = edge[i].v;
  69. if(dis[v] > dis[u] + edge[i].w)
  70. {
  71. dis[v] = dis[u] + edge[i].w;
  72. if (!inq[v])
  73. {
  74. inq[v] = true;
  75. q.push(v);
  76. cnt[v]++;
  77. }
  78. if (cnt[v] >= N) return true;
  79. }
  80. }
  81. }
  82. return false;
  83. }
  84.  
  85. int main()
  86. {
  87. int T;
  88. scanf("%d",&T);
  89. while (T--)
  90. {
  91. init();
  92. scanf("%d%d%d",&N,&M,&W);
  93. for (int i = ; i < M ; i++)
  94. {
  95. int u,v,w;
  96. scanf("%d%d%d",&u,&v,&w);
  97. add_edge(u,v,w);
  98. add_edge(v,u,w);
  99. }
  100. for (int i = ; i < W ; i++)
  101. {
  102. int u,v,w;
  103. scanf("%d%d%d",&u,&v,&w);
  104. add_edge(u,v,-w);
  105. }
  106. if (SPFA()) puts("YES");
  107. else puts("NO");
  108. }
  109. return ;
  110. }
  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const int INF = 0x3f3f3f3f;
  25. struct Edge
  26. {
  27. int u,v,next;
  28. int w;
  29. }edge[MAXM];
  30. int tot;
  31. int N,M,W;
  32.  
  33. int dis[MAXN];
  34. bool bellman_ford()
  35. {
  36. for (int i = ; i <= N ; i++) dis[i] = INF;
  37. dis[] = ;
  38. for (int i = ; i <= N - ; i++)
  39. {
  40. for (int j = ; j < tot ; j++)
  41. {
  42. int u = edge[j].u;
  43. int v = edge[j].v;
  44. int w = edge[j].w;
  45. if (dis[u] < INF && dis[v] > dis[u] + w)
  46. {
  47. dis[v] = dis[u] + w;
  48. }
  49. }
  50. }
  51. for (int i = ; i < tot ; i++)
  52. {
  53. int u = edge[i].u;
  54. int v = edge[i].v;
  55. int w = edge[i].w;
  56. if (dis[u] < INF && dis[v] > dis[u] + w)
  57. return true;
  58. }
  59. return false;
  60. }
  61.  
  62. int main()
  63. {
  64. int T;
  65. scanf("%d",&T);
  66. while (T--)
  67. {
  68. scanf("%d%d%d",&N,&M,&W);
  69. tot = ;
  70. for (int i = ; i < M ; i++)
  71. {
  72. int u,v,w;
  73. scanf("%d%d%d",&u,&v,&w);
  74. edge[tot].u = u;
  75. edge[tot].v = v;
  76. edge[tot].w = w;
  77. tot++;
  78. edge[tot].v = u;
  79. edge[tot].u = v;
  80. edge[tot].w = w;
  81. tot++;
  82. }
  83. for (int i = ; i < W ; i++)
  84. {
  85. int u,v,w;
  86. scanf("%d%d%d",&u,&v,&w);
  87. edge[tot].u = u;
  88. edge[tot].v = v;
  89. edge[tot].w = -w;
  90. tot++;
  91. }
  92. if (bellman_ford()) puts("YES");
  93. else puts("NO");
  94. }
  95. return ;
  96. }

POJ 1502 MPI Maelstrom

阅读题,floyd做

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int INF = 0x3f3f3f3f;
  24. int dp[MAXN][MAXN];
  25. int N;
  26.  
  27. void slove()
  28. {
  29. for (int k = ; k <= N ; k++)
  30. {
  31. for (int i = ; i <= N; i++)
  32. for (int j = ; j <= N ; j++)
  33. {
  34. dp[i][j] = min(dp[i][j],dp[i][k] + dp[k][j]);
  35. }
  36. }
  37. int ret = ;
  38. for (int i = ; i <= N ; i++)
  39. ret = max(dp[][i],ret);
  40. printf("%d\n",ret);
  41. }
  42.  
  43. int main()
  44. {
  45. while (scanf("%d",&N) != EOF)
  46. {
  47. dp[][] = ;
  48. for (int i = ; i <= N ; i++)
  49. {
  50. dp[i][i] = ;
  51. for (int j = ; j <= i - ; j++)
  52. {
  53. char tmp[];
  54. scanf("%s",tmp);
  55. if (tmp[] == 'x') dp[i][j] = INF;
  56. else dp[i][j] = atoi(tmp);
  57. dp[j][i] = dp[i][j];
  58. }
  59. }
  60. slove();
  61. }
  62. return ;
  63. }

POJ 3660 Cow Contest

题意:给出了一系列比赛结果。比如其中一场比赛描述为A.B 说明A的能力值大于B。问最后有几个人的能力值的排名可以根据这几场比赛完全确定。floyd传递闭包

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int INF = 0x3f3f3f3f;
  24. bool dp[MAXN][MAXN];
  25. int main()
  26. {
  27. int N,M;
  28. while (scanf("%d%d",&N,&M) != EOF)
  29. {
  30. memset(dp,false,sizeof(dp));
  31. for (int i = ; i <= M ; i++)
  32. {
  33. int u,v;
  34. scanf("%d%d",&u,&v);
  35. dp[u][v] = true;
  36. }
  37. for (int k = ; k <= N ; k++)
  38. for (int i = ; i <= N ; i++)
  39. for (int j = ; j <= N ; j++)
  40. if (dp[i][k] && dp[k][j]) dp[i][j] = true;
  41. int ret = ;
  42. for (int i = ; i <= N ; i++)
  43. {
  44. int cnt = ;
  45. for (int j = ; j <= N ; j++)
  46. cnt += dp[i][j] + dp[j][i];
  47. if (cnt == N - ) ret++;
  48. }
  49. printf("%d\n",ret);
  50. }
  51. return ;
  52. }

POJ 2240 Arbitrage

字符串map处理一下,然后直接floyd处理即可

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const double eps = 1e-;
  24. double dp[MAXN][MAXN];
  25. int N;
  26. map<string,int>mp;
  27. int main()
  28. {
  29. // freopen("sample.txt","r",stdin);
  30. int kase = ;
  31. while (scanf("%d",&N) != EOF)
  32. {
  33. if (N == ) break;
  34. mp.clear();
  35. char str[],tmp[];
  36. int cas = ;
  37. for (int i = ; i < N ; i++)
  38. {
  39. scanf("%s",str);
  40. if (!mp[str]) mp[str] = cas++;
  41. }
  42. int M;
  43. for (int i = ; i <= N ; i++)
  44. {
  45. for (int j = ; j <= N ; j++)
  46. dp[i][j] = 0.0;
  47. }
  48. for (int i = ; i <= N ; i++)
  49. dp[i][i] = 1.0;
  50.  
  51. scanf("%d",&M);
  52. for (int i = ; i < M ; i++)
  53. {
  54. double x;
  55. scanf("%s%lf%s",str,&x,tmp);
  56. int l = mp[str];
  57. int r = mp[tmp];
  58. dp[l][r] = max(dp[l][r],x);
  59. }
  60. for (int k = ; k <= N ; k++)
  61. {
  62. for (int i = ; i <= N ; i++)
  63. for (int j = ; j <= N ; j++)
  64. dp[i][j] = max(dp[i][j],dp[i][k] * dp[k][j]);
  65. }
  66. double ret = 0.0;
  67. for (int i = ; i <= N ; i++)
  68. ret = max(ret,dp[i][i]);
  69. if (ret - 1.0 > eps) printf("Case %d: Yes\n",kase++);
  70. else printf("Case %d: No\n",kase++);
  71. }
  72. return ;
  73. }

POJ 1511 Invitation Cards

题目大意:给出n个点和n条有向边,求所有点到源点1的来回最短路之和(保证每个点都可以往返源点1)

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const LL INF = 1e17;
  25. int P,Q;
  26. struct Edge
  27. {
  28. int u,v,next;
  29. LL w;
  30. }edge[MAXN];
  31.  
  32. struct heapnode
  33. {
  34. LL val;
  35. int u;
  36. bool operator < (const heapnode & rhs) const
  37. {
  38. return val > rhs.val;
  39. }
  40. };
  41.  
  42. struct Dijkstra
  43. {
  44. int N,M;
  45. Edge edge[MAXM];
  46. int tot ,head[MAXN];
  47. LL dis[MAXN];
  48. bool done[MAXN];
  49. priority_queue<heapnode>q;
  50.  
  51. void init(int n,int m)
  52. {
  53. memset(head,-,sizeof(head));
  54. tot = ;
  55. N = n;
  56. M = m;
  57. }
  58.  
  59. void add_edge(int u,int v,LL w)
  60. {
  61. edge[tot].u = u;
  62. edge[tot].v = v;
  63. edge[tot].w = w;
  64. edge[tot].next = head[u];
  65. head[u] = tot++;
  66. }
  67.  
  68. void dijkstra(int s)
  69. {
  70. for (int i = ; i <= N ; i++) dis[i] = INF;
  71. while (!q.empty()) q.pop();
  72. memset(done,false,sizeof(done));
  73. dis[s] = ;
  74. q.push((heapnode){dis[s],s});
  75. while (!q.empty())
  76. {
  77. heapnode x = q.top(); q.pop();
  78. int u = x.u;
  79. for (int i = head[u] ; i != - ; i = edge[i].next)
  80. {
  81. int v = edge[i].v;
  82. if (dis[v] > dis[u] + edge[i].w)
  83. {
  84. dis[v] = dis[u] + edge[i].w;
  85. q.push((heapnode){dis[v],v});
  86. }
  87. }
  88. }
  89. }
  90. }first,second;
  91.  
  92. int main()
  93. {
  94. int T,kase = ;
  95. scanf("%d",&T);
  96. while (T--)
  97. {
  98. scanf("%d%d",&P,&Q);
  99. for (int i = ; i < Q ; i++)
  100. {
  101. scanf("%d%d%I64d",&edge[i].u,&edge[i].v,&edge[i].w);
  102. }
  103. first.init(P,Q);
  104. for (int i = ; i < Q ; i++)
  105. {
  106. first.add_edge(edge[i].u,edge[i].v,edge[i].w);
  107. }
  108. first.dijkstra();
  109. second.init(P,Q);
  110. for (int i = ; i < Q ; i++)
  111. {
  112. second.add_edge(edge[i].v,edge[i].u,edge[i].w);
  113. }
  114. second.dijkstra();
  115. LL ret = ;
  116. for (int i = ; i <= P ; i++)
  117. ret = ret + first.dis[i] + second.dis[i];
  118. printf("%I64d\n",ret);
  119. }
  120. return ;
  121. }

POJ 3159 Candies
差分约束+SPFA

给n个人派糖果,给出m组数据,每组数据包含A,B,c  三个数,
意思是A的糖果数比B少的个数不多于c,即B的糖果数 - A的糖果数<= c 。
最后求n 比 1 最多多多少糖果。

贴一下kuangbin神的题解吧

【解题思路】
这是一题典型的差分约束题。不妨将糖果数当作距离,把相差的最大糖果数看成有向边AB的权值,
我们得到 dis[B]-dis[A]<=w(A,B)。看到这里,我们联想到求最短路时的松弛技术,
即if(dis[B]>dis[A]+w(A,B), dis[B]=dis[A]+w(A,B)。
即是满足题中的条件dis[B]-dis[A]<=w(A,B),由于要使dis[B] 最大,
所以这题可以转化为最短路来求。
这题如果用SPFA 算法的话,则需要注意不能用spfa+queue 来求,会TLE ,而是用 spfa + stack

我自己直接dijkstra+优先队列是可以的。2个都贴一下
dijkstra

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const LL INF = 1e17;
  25. int N,M;
  26. struct Edge
  27. {
  28. int u,v,next;
  29. LL w;
  30. };
  31.  
  32. struct heapnode
  33. {
  34. LL val;
  35. int u;
  36. bool operator < (const heapnode & rhs) const
  37. {
  38. return val > rhs.val;
  39. }
  40. };
  41.  
  42. struct Dijksta
  43. {
  44. int N,M;
  45. int head[MAXN],tot;
  46. Edge edge[MAXM];
  47. bool done[MAXN];
  48. LL dis[MAXN];
  49. priority_queue<heapnode>q;
  50.  
  51. void init(int n,int m)
  52. {
  53. memset(head,-,sizeof(head));
  54. tot = ;
  55. N = n;
  56. M = m;
  57. }
  58.  
  59. void add_edge(int u,int v,LL w)
  60. {
  61. edge[tot].u = u;
  62. edge[tot].v = v;
  63. edge[tot].w = w;
  64. edge[tot].next = head[u];
  65. head[u] = tot++;
  66. }
  67.  
  68. void dijkstra(int s)
  69. {
  70. for (int i = ; i <= N ; i++) dis[i] = INF;
  71. memset(done,false,sizeof(done));
  72. while (!q.empty()) q.pop();
  73. dis[s] = ;
  74. q.push((heapnode){dis[s],s});
  75. while (!q.empty())
  76. {
  77. heapnode x = q.top(); q.pop();
  78. int u = x.u;
  79. // cout << u << " " << dis[u] << endl;
  80. if (done[u]) continue;
  81. done[u] = true;
  82. for (int i = head[u] ; i != - ; i = edge[i].next)
  83. {
  84. int v = edge[i].v;
  85. if (dis[v] > dis[u] + edge[i].w)
  86. {
  87. dis[v] = dis[u] + edge[i].w;
  88. q.push((heapnode){dis[v],v});
  89. }
  90. }
  91. }
  92. }
  93. }src;
  94.  
  95. int main()
  96. {
  97. while (scanf("%d%d",&N,&M) != EOF)
  98. {
  99. src.init(N,M);
  100. for (int i = ; i < M ; i++)
  101. {
  102. int u,v;
  103. LL w;
  104. scanf("%d%d%I64d",&u,&v,&w);
  105. src.add_edge(u,v,w);
  106. }
  107. src.dijkstra();
  108. printf("%I64d\n",src.dis[N]);
  109. }
  110. return ;
  111. }

spfa + stack

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const int INF = 0x3f3f3f3f;
  25. int head[MAXN],tot;
  26. struct Edge
  27. {
  28. int u,v,next;
  29. int w;
  30. }edge[MAXM];
  31. int N,M;
  32.  
  33. void init()
  34. {
  35. memset(head,-,sizeof(head));
  36. tot = ;
  37. }
  38.  
  39. void add_edge(int u,int v,int w)
  40. {
  41. edge[tot].u = u;
  42. edge[tot].v = v;
  43. edge[tot].w = w;
  44. edge[tot].next = head[u];
  45. head[u] = tot++;
  46. }
  47.  
  48. bool inq[MAXN];
  49. int Stack[MAXN + MAXN];
  50. int top;
  51. int dis[MAXN];
  52. void Spfa(int s)
  53. {
  54. int top = ;
  55. for (int i = ; i <= N ; i++) dis[i] = INF;
  56. memset(inq,false,sizeof(inq));
  57. inq[s] = true;
  58. top = ;
  59. Stack[++top] = s;
  60. dis[s] = ;
  61. while (top != )
  62. {
  63. int u = Stack[top];
  64. top--;
  65. inq[u] = false;
  66. for (int i = head[u]; i != - ; i = edge[i].next)
  67. {
  68. int v = edge[i].v;
  69. if (dis[v] > dis[u] + edge[i].w)
  70. {
  71. dis[v] = dis[u] + edge[i].w;
  72. if (!inq[v])
  73. {
  74. inq[v] = true;
  75. Stack[++top] = v;
  76. }
  77. }
  78. }
  79. }
  80. }
  81.  
  82. int main()
  83. {
  84. while (scanf("%d%d",&N,&M) != EOF)
  85. {
  86. init();
  87. for (int i = ; i < M ; i++)
  88. {
  89. int u,v,w;
  90. scanf("%d%d%d",&u,&v,&w);
  91. add_edge(u,v,w);
  92. }
  93. Spfa();
  94. printf("%d\n",dis[N]);
  95. }
  96. return ;
  97. }

POJ 2502 Subway
读完提按照他说的来建图即可

我记得当时做的时候感觉超级NM坑。我不知道我自己的建图哪里WA了。反正就换一种别人的写法救过了。我真的不服。。

  1. #include <set>
  2. #include <list>
  3. #include <cmath>
  4. #include <ctime>
  5. #include <deque>
  6. #include <stack>
  7. #include <queue>
  8. #include <cctype>
  9. #include <cstdio>
  10. #include <string>
  11. #include <vector>
  12. #include <climits>
  13. #include <cstdlib>
  14. #include <cstring>
  15. #include <iostream>
  16. #include <algorithm>
  17. #define LL long long
  18. #define PI 3.1415926535897932626
  19. using namespace std;
  20. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  21. const int MAXN = ;
  22. const int MAXM = MAXN * MAXN;
  23. const double walkv = * 1000.0 / 60.0;
  24. const double subv = * 1000.0 / 60.0;
  25. const double INF = 1e17;
  26. const double eps = 1e-;
  27. struct Edge
  28. {
  29. int u,v,next;
  30. double w;
  31. bool walk;
  32. };
  33.  
  34. struct heapnode
  35. {
  36. double val;
  37. int u;
  38. bool operator < (const heapnode & rhs) const
  39. {
  40. return val > rhs.val;
  41. }
  42. };
  43.  
  44. struct Dijkstra
  45. {
  46. int N,M;
  47. bool done[MAXN];
  48. int head[MAXN],tot;
  49. Edge edge[MAXM];
  50. priority_queue<heapnode>q;
  51. double dis[MAXN];
  52.  
  53. void init(int n,int m)
  54. {
  55. N = n;
  56. M = m;
  57. memset(head,-,sizeof(head));
  58. tot = ;
  59. }
  60.  
  61. void add_edge(int u ,int v,double w,bool walk)
  62. {
  63. edge[tot].u = u;
  64. edge[tot].v = v;
  65. edge[tot].w = w;
  66. edge[tot].next = head[u];
  67. edge[tot].walk = walk;
  68. head[u] = tot++;
  69. }
  70.  
  71. void dijkstra(int s)
  72. {
  73. memset(done,false,sizeof(done));
  74. while (!q.empty()) q.pop();
  75. for (int i = ; i <= N ; i++) dis[i] = INF;
  76. dis[s] = 0.0;
  77. q.push((heapnode){dis[s],s});
  78. while (!q.empty())
  79. {
  80. heapnode x = q.top(); q.pop();
  81. int u = x.u;
  82. if (done[u])continue;
  83. done[u] = true;
  84. for (int i = head[u] ; i != - ; i = edge[i].next)
  85. {
  86. int v = edge[i].v;
  87. double tmp;
  88. if (edge[i].walk)
  89. tmp = dis[u] + edge[i].w / walkv ;
  90. else tmp = dis[u] + edge[i].w / subv;
  91.  
  92. if (dis[v] > tmp)
  93. {
  94. dis[v] = tmp;
  95. q.push((heapnode){dis[v],v});
  96. }
  97. }
  98. }
  99. }
  100. }src;
  101.  
  102. struct point
  103. {
  104. double x,y;
  105. int id;
  106. }st,ed,res[MAXN];
  107. double map[MAXN][MAXN];
  108. bool sub[MAXN][MAXN];
  109. int cas,tot;
  110.  
  111. double dis(point &a, point &b)
  112. {
  113. point p;
  114. p.x = a.x - b.x;
  115. p.y = a.y - b.y;
  116. return sqrt(p.x * p.x + p.y * p.y);
  117. }
  118.  
  119. int main()
  120. {
  121. // freopen("sample.txt","r",stdin);
  122. src.init(MAXN,MAXM);
  123. for (int i = ; i < MAXN ; i++)
  124. for (int j = ; j < MAXN ; j++) map[i][j] = -1.0;
  125. for (int i = ; i < ; i++) scanf("%lf%lf",&res[i].x,&res[i].y);
  126. tot = ;
  127. point last,now;
  128. last.x = last.y = -;
  129. while (scanf("%lf%lf", &now.x, &now.y) != EOF)
  130. {
  131. if (!(now.x == - && now.y == -))
  132. {
  133. res[tot++] = now;
  134. if (!(last.x == - && last.y == -))
  135. {
  136. src.add_edge(tot - ,tot - ,dis(res[tot - ],res[tot - ]),false);
  137. src.add_edge(tot - ,tot - ,dis(res[tot - ],res[tot - ]),false);
  138. }
  139. }
  140. last = now;
  141. }
  142.  
  143. for (int i = ; i < tot ; i++)
  144. for (int j = ; j < tot ; j++)
  145. if (map[i][j] == -)
  146. {
  147. map[i][j] = dis(res[i],res[j]);
  148. sub[i][j] = false;
  149. src.add_edge(i,j,map[i][j],true);
  150. src.add_edge(j,i,map[i][j],true);
  151. }
  152. src.dijkstra();
  153. printf("%.0f\n",src.dis[]);
  154. return ;
  155. }

POJ 1062 昂贵的聘礼
读完提见图就行了

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL int
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = MAXN * MAXN;
  24. const int INF = 0x3f3f3f3f;
  25. int M,N;
  26. struct Edge
  27. {
  28. int u,v,next;
  29. int w;
  30. };
  31.  
  32. struct heapnode
  33. {
  34. int val;
  35. int u;
  36. bool operator < (const heapnode & rhs) const
  37. {
  38. return val > rhs.val;
  39. }
  40. };
  41.  
  42. struct Dijksta
  43. {
  44. int N,M;
  45. int head[MAXN],tot;
  46. Edge edge[MAXM];
  47. bool done[MAXN];
  48. LL dis[MAXN];
  49.  
  50. void init(int n,int m)
  51. {
  52. memset(head,-,sizeof(head));
  53. tot = ;
  54. N = n;
  55. M = m;
  56. }
  57.  
  58. void add_edge(int u,int v,int w)
  59. {
  60. edge[tot].u = u;
  61. edge[tot].v = v;
  62. edge[tot].w = w;
  63. edge[tot].next = head[u];
  64. head[u] = tot++;
  65. }
  66.  
  67. void dijkstra(int s)
  68. {
  69. for (int i = ; i <= N ; i++) dis[i] = INF;
  70. dis[s] = ;
  71. // cout << " 122323" << endl;
  72. memset(done,false,sizeof(done));
  73. // cout << "sdsdsdw" << endl;
  74. priority_queue<heapnode>q;
  75. // cout << "!213131" << endl;
  76. q.push((heapnode){dis[s],s});
  77. while (!q.empty())
  78. {
  79. heapnode x = q.top(); q.pop();
  80. int u = x.u;
  81. // printf("%d %d\n",u,dis[u]);
  82. if (done[u]) continue;
  83. done[u] = true;
  84. for (int i = head[u] ; i != - ; i = edge[i].next)
  85. {
  86. int v = edge[i].v;
  87. if (dis[v] > dis[u] + edge[i].w)
  88. {
  89. dis[v] = dis[u] + edge[i].w;
  90. q.push((heapnode){dis[v],v});
  91. }
  92. }
  93. }
  94. }
  95. }src;
  96.  
  97. struct node
  98. {
  99. int P,L,X;
  100. int T[MAXN],V[MAXN];
  101. }res[MAXN];
  102.  
  103. int main()
  104. {
  105. while (scanf("%d%d",&M,&N) != EOF)
  106. {
  107. for (int i = ; i <= N ; i++)
  108. {
  109. scanf("%d%d%d",&res[i].P,&res[i].L,&res[i].X);
  110. for (int j = ; j <= res[i].X ; j++)
  111. scanf("%d%d",&res[i].T[j],&res[i].V[j]);
  112. }
  113. int ret = INF;
  114. for (int i = ; i <= N ; i++)
  115. {
  116. src.init(MAXN,MAXM);
  117. for (int j = ; j <= N ; j++) src.add_edge(,j,res[j].P);
  118. int minlevel = res[i].L;
  119. for (int j = ; j <= N ; j++)
  120. {
  121. if (res[j].L - minlevel > M || minlevel > res[j].L) continue;
  122. else
  123. {
  124. //if (i == 2) cout << j << " " << res[j].L << endl;
  125. for (int k = ; k <= res[j].X ; k++)
  126. {
  127. if (res[res[j].T[k]].L - minlevel > M || minlevel > res[res[j].T[k]].L) continue;
  128. src.add_edge(res[j].T[k],j,res[j].V[k]);
  129. }
  130. }
  131. }
  132. //cout << "1111" << endl;
  133. src.dijkstra();
  134. ret = min(ret,src.dis[]);
  135. }
  136. printf("%d\n",ret);
  137. }
  138. return ;
  139. }

POJ 1847 Tram

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL int
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = MAXN * MAXN;
  24. const int INF = 0x3f3f3f3f;
  25. int N,M,A,B;
  26. struct Edge
  27. {
  28. int u,v,next;
  29. LL w;
  30. };
  31.  
  32. struct heapnode
  33. {
  34. LL val;
  35. int u;
  36. bool operator < (const heapnode & rhs) const
  37. {
  38. return val > rhs.val;
  39. }
  40. };
  41.  
  42. struct Dijksta
  43. {
  44. int N,M;
  45. int head[MAXN],tot;
  46. Edge edge[MAXM];
  47. bool done[MAXN];
  48. LL dis[MAXN];
  49. //priority_queue<heapnode>q;
  50.  
  51. void init(int n,int m)
  52. {
  53. memset(head,-,sizeof(head));
  54. tot = ;
  55. N = n;
  56. M = m;
  57. }
  58.  
  59. void add_edge(int u,int v,LL w)
  60. {
  61. edge[tot].u = u;
  62. edge[tot].v = v;
  63. edge[tot].w = w;
  64. edge[tot].next = head[u];
  65. head[u] = tot++;
  66. }
  67.  
  68. void dijkstra(int s)
  69. {
  70. for (int i = ; i <= N ; i++) dis[i] = INF;
  71. memset(done,false,sizeof(done));
  72. priority_queue<heapnode>q;
  73. dis[s] = ;
  74. q.push((heapnode){dis[s],s});
  75. while (!q.empty())
  76. {
  77. heapnode x = q.top(); q.pop();
  78. int u = x.u;
  79. // cout << u << " " << dis[u] << endl;
  80. if (done[u]) continue;
  81. done[u] = true;
  82. for (int i = head[u] ; i != - ; i = edge[i].next)
  83. {
  84. int v = edge[i].v;
  85. if (dis[v] > dis[u] + edge[i].w)
  86. {
  87. dis[v] = dis[u] + edge[i].w;
  88. q.push((heapnode){dis[v],v});
  89. }
  90. }
  91. }
  92. }
  93. }src;
  94.  
  95. int main()
  96. {
  97. while (scanf("%d%d%d",&N,&A,&B) != EOF)
  98. {
  99. src.init(MAXN,MAXM);
  100. for (int i = ; i <= N ; i++)
  101. {
  102. int cnt ;
  103. scanf("%d",&cnt);
  104. for (int j = ; j <= cnt ; j++)
  105. {
  106. int x;
  107. scanf("%d",&x);
  108. if (j == ) src.add_edge(i,x,);
  109. else src.add_edge(i,x,);
  110. }
  111. }
  112. src.dijkstra(A);
  113. printf("%d\n",src.dis[B] == INF ? - : src.dis[B]);
  114. }
  115. return ;
  116. }

题意:告诉n个点,每个点都有一个权值,A 到 B的时间等于 (val[b]-val[a])^3  都是单向边,可能存在负环,Q次询问,问从1到询问点的最短路,如果不可达或者点在负环上或者小于3,那么就输出? 否则输出最短路径值

标记负环上的点。

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = MAXN * MAXN;
  24. const int INF = 0x3f3f3f3f;
  25. queue<int>q;
  26. int N,M;
  27. struct Edge
  28. {
  29. int u,v,next;
  30. int w;
  31. };
  32.  
  33. struct Spfa
  34. {
  35. int N,M;
  36. bool inq[MAXN];
  37. int dp[MAXN],cnt[MAXN];
  38. int pre[MAXN];
  39. int head[MAXN],tot;
  40. int dis[MAXN];
  41. bool incir[MAXN];
  42. Edge edge[MAXM];
  43.  
  44. void init(int n,int m)
  45. {
  46. N = n;
  47. M = m;
  48. tot = ;
  49. memset(head,-,sizeof(head));
  50. memset(cnt,,sizeof(cnt));
  51. }
  52.  
  53. void add_edge(int u,int v,int w)
  54. {
  55. edge[tot].u = u;
  56. edge[tot].v = v;
  57. edge[tot].w = w;
  58. edge[tot].next = head[u];
  59. head[u] = tot++;
  60. }
  61.  
  62. void dfs(int pos)
  63. {
  64. incir[pos] = true;
  65. for (int i = head[pos] ; i != - ; i = edge[i].next)
  66. {
  67. int v = edge[i].v;
  68. if (!incir[v])
  69. dfs(v);
  70. }
  71. }
  72.  
  73. void spfa(int s)
  74. {
  75. memset(incir,false,sizeof(incir));
  76. memset(inq,false,sizeof(inq));
  77. for (int i = ; i <= N ; i++) dis[i] = INF;
  78. while (!q.empty()) q.pop();
  79. q.push(s);
  80. dis[s] = ;
  81. cnt[s] = ;
  82. inq[s] = true;
  83. while (!q.empty())
  84. {
  85. int u = q.front(); q.pop();
  86. inq[u] = false;
  87. for (int i = head[u] ; i != - ; i = edge[i].next)
  88. {
  89. int v = edge[i].v;
  90. if (incir[v]) continue;
  91. if (dis[v] > dis[u] + edge[i].w)
  92. {
  93. dis[v] = dis[u] + edge[i].w;
  94. if (!inq[v])
  95. {
  96. inq[v] = true;
  97. cnt[v]++;
  98. q.push(v);
  99. if (cnt[v] >= N) dfs(v);
  100. }
  101. }
  102. }
  103. }
  104. }
  105. }src;
  106.  
  107. int res[MAXN];
  108.  
  109. int main()
  110. {
  111. // freopen("sample.txt","r",stdin);
  112. int T,kase = ;
  113. scanf("%d",&T);
  114. while(T--)
  115. {
  116. scanf("%d",&N);
  117. for (int i = ; i <= N ; i++) scanf("%d",&res[i]);
  118. scanf("%d",&M);
  119. src.init(N,M);
  120. for (int i = ; i <= M ; i++)
  121. {
  122. int u,v;
  123. scanf("%d%d",&u,&v);
  124. src.add_edge(u,v,(res[v] - res[u]) * (res[v] - res[u]) *
  125. (res[v] - res[u]));
  126. }
  127. src.spfa();
  128. printf("Case %d:\n",kase++);
  129. int q;
  130. scanf("%d",&q);
  131. while (q--)
  132. {
  133. int u;
  134. scanf("%d",&u);
  135. if (src.incir[u] || src.dis[u] < || src.dis[u] >= INF)
  136. printf("?\n");
  137. else printf("%d\n",src.dis[u]);
  138. }
  139. }
  140. return ;
  141. }

HDU 4725 The Shortest Path in Nya Graph

总共3*N个点,1-N个点,N + 1 ---- N + N + N 这几个点分别是拆点的点。

至于为什么要拆点,注意到在一层的点不一定能直接到达。参考数据

3 0 1

1 1 1 ans = -1;

所有层拆点分为前向点 后项点。 见图为点连层前向点,层层之间后连前,具体看代码

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = MAXN * ;
  24. const int INF = 0x3f3f3f3f;
  25. struct Edge
  26. {
  27. int u,v,w;
  28. int next;
  29. }edge[MAXM];
  30. int head[MAXN],tot;
  31.  
  32. void init()
  33. {
  34. memset(head,-,sizeof(head));
  35. tot = ;
  36. }
  37.  
  38. void add_edge(int u,int v,int w)
  39. {
  40. edge[tot].u = u;
  41. edge[tot].v = v;
  42. edge[tot].w = w;
  43. edge[tot].next = head[u];
  44. head[u] = tot++;
  45. }
  46.  
  47. struct heapnode
  48. {
  49. int val,u;
  50. bool operator < (const heapnode &rhs) const
  51. {
  52. return val > rhs.val;
  53. }
  54. };
  55.  
  56. priority_queue<heapnode>q;
  57. bool done[MAXN];
  58. int dis[MAXN];
  59.  
  60. void dijkstra(int s)
  61. {
  62. memset(done,false,sizeof(done));
  63. while (!q.empty()) q.pop();
  64. memset(dis,0x3f,sizeof(dis));
  65. dis[s] = ;
  66. heapnode tmp;
  67. tmp.val = dis[s];
  68. tmp.u = s;
  69. q.push(tmp);
  70. while (!q.empty())
  71. {
  72. heapnode x = q.top(); q.pop();
  73. int u = x.u;
  74. if (done[u]) continue;
  75. done[u] = true;
  76. for (int i = head[u] ; i != - ; i = edge[i].next)
  77. {
  78. int v = edge[i].v;
  79. if (dis[v] > dis[u] + edge[i].w)
  80. {
  81. dis[v] = dis[u] + edge[i].w;
  82. heapnode tmp;
  83. tmp.val = dis[v];
  84. tmp.u = v;
  85. q.push(tmp);
  86. }
  87. }
  88. }
  89. }
  90.  
  91. int N,M,C;
  92. int main()
  93. {
  94. //freopen("Sample.txt","r",stdin);
  95. int T,kase = ;
  96. scanf("%d",&T);
  97. while (T--)
  98. {
  99. scanf("%d%d%d",&N,&M,&C);
  100. init();
  101. for (int i = ; i <= N ; i++)
  102. {
  103. int x;
  104. scanf("%d",&x);
  105. add_edge(i,N + x,);
  106. add_edge(N + N + x,i,);
  107. }
  108. for (int i = ; i < N ; i++)
  109. {
  110. add_edge(N + i,N + N + i + ,C);
  111. add_edge(N + i + ,N + N + i,C);
  112. }
  113. for (int i = ; i < M ; i++)
  114. {
  115. int u,v,w;
  116. scanf("%d%d%d",&u,&v,&w);
  117. add_edge(u,v,w);
  118. add_edge(v,u,w);
  119. }
  120. // for (int i = 0 ; i < tot ; i++)
  121. // printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].w);
  122. dijkstra();
  123. if (dis[N] == INF) dis[N] = -;
  124. printf("Case #%d: %d\n",kase++,dis[N]);
  125.  
  126. }
  127. return ;
  128. }

HDU 3416 Marriage Match IV

最短路的所有边只能走一次。直接最短路+最大流

这里唯一的问题就是最短路树是什么样子的。有向图和无向图的设置不太一样。前面连通图专题里有无向图的这里有向图的我相关的已经注释区分了

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const int INF = 0x3f3f3f3f;
  25. struct Edge
  26. {
  27. int u,v,w;
  28. int next;
  29. int id;
  30. bool cut;
  31. };
  32.  
  33. struct heapnode
  34. {
  35. int val,u;
  36. bool operator < (const heapnode &rhs) const
  37. {
  38. return val > rhs.val;
  39. }
  40. };
  41.  
  42. priority_queue<heapnode>q;
  43.  
  44. struct Dijkstra
  45. {
  46. int N,M;
  47. int dis[MAXN];
  48. bool done[MAXN];
  49. int head[MAXN],tot;
  50. Edge edge[MAXM];
  51.  
  52. void init(int n)
  53. {
  54. memset(head,-,sizeof(head));
  55. tot = ;
  56. N = n;
  57. }
  58.  
  59. void add_edge(int u,int v,int w,int id)
  60. {
  61. edge[tot].u = u;
  62. edge[tot].v = v;
  63. edge[tot].w = w;
  64. edge[tot].id = id;
  65. edge[tot].next = head[u];
  66. head[u] = tot++;
  67. }
  68.  
  69. void dijkstra(int s)
  70. {
  71. memset(done,false,sizeof(done));
  72. for (int i = ; i <= N ; i++) dis[i] = INF;
  73. dis[s] = ;
  74. while (!q.empty()) q.pop();
  75. q.push((heapnode){dis[s],s});
  76. while (!q.empty())
  77. {
  78. heapnode x = q.top(); q.pop();
  79. int u = x.u;
  80. // cout << u << " " << dis[u] << endl ;
  81. if (done[u]) continue;
  82. done[u] = true;
  83. for (int i = head[u] ; i != - ; i = edge[i].next)
  84. {
  85. int v = edge[i].v;
  86. if (dis[v] > dis[u] + edge[i].w)
  87. {
  88. dis[v] = dis[u] + edge[i].w;
  89. q.push((heapnode){dis[v],v});
  90. }
  91. }
  92. }
  93. }
  94.  
  95. }St,Ted;
  96.  
  97. struct Edge2
  98. {
  99. int u,v,next;
  100. int cap,flow;
  101. }edge[MAXM];
  102. int head[MAXN],tot;
  103. int gap[MAXN],dep[MAXN],cur[MAXN];
  104.  
  105. void init()
  106. {
  107. memset(head,-,sizeof(head));
  108. tot = ;
  109. }
  110.  
  111. void add_edge(int u,int v,int cap,int rcap = )
  112. {
  113. edge[tot].u = u;
  114. edge[tot].v = v;
  115. edge[tot].cap = cap;
  116. edge[tot].flow = ;
  117. edge[tot].next = head[u];
  118. head[u] = tot++;
  119.  
  120. edge[tot].u = v;
  121. edge[tot].v = u;
  122. edge[tot].cap = rcap;
  123. edge[tot].flow = ;
  124. edge[tot].next = head[v];
  125. head[v] = tot++;
  126. }
  127.  
  128. int Q[MAXN];
  129. void BFS(int st,int ed)
  130. {
  131. memset(dep,-,sizeof(dep));
  132. memset(gap,,sizeof(gap));
  133. gap[] = ;
  134. int front = ,rear = ;
  135. dep[ed] = ;
  136. Q[rear++] = ed;
  137. while (front < rear)
  138. {
  139. int u = Q[front++];
  140. for (int i = head[u] ; i != - ; i = edge[i].next)
  141. {
  142. int v = edge[i].v;
  143. if (dep[v] != -) continue;
  144. Q[rear++] = v;
  145. dep[v] = dep[u] + ;
  146. gap[dep[v]]++;
  147. }
  148. }
  149. }
  150.  
  151. int S[MAXN];
  152. int sap(int st,int ed,int N)
  153. {
  154. BFS(st,ed);
  155. memcpy(cur,head,sizeof(head));
  156. int top = ;
  157. int u = st;
  158. int ans = ;
  159. while (dep[st] < N)
  160. {
  161. if (u == ed)
  162. {
  163. int Min = INF;
  164. int inser;
  165. for (int i = ; i < top ; i++)
  166. {
  167. if (Min > edge[S[i]].cap - edge[S[i]].flow)
  168. {
  169. Min = edge[S[i]].cap - edge[S[i]].flow;
  170. inser = i;
  171. }
  172. }
  173. for (int i = ; i < top ; i++)
  174. {
  175. edge[S[i]].flow += Min;
  176. edge[S[i] ^ ].flow -=Min;
  177. }
  178. ans += Min;
  179. top = inser;
  180. u = edge[S[top] ^ ].v;
  181. continue;
  182. }
  183. bool flag = false;
  184. int v;
  185. for (int i = cur[u] ; i != - ; i = edge[i].next)
  186. {
  187. v = edge[i].v;
  188. if (edge[i].cap - edge[i].flow && dep[v] + == dep[u])
  189. {
  190. flag = true;
  191. cur[u] = i;
  192. break;
  193. }
  194. }
  195. if(flag)
  196. {
  197. S[top++] = cur[u];
  198. u = v;
  199. continue;
  200. }
  201. int Min = N;
  202. for (int i = head[u] ; i != - ; i = edge[i].next)
  203. {
  204. if (edge[i].cap - edge[i].flow && dep[edge[i].v] < Min)
  205. {
  206. Min = dep[edge[i].v];
  207. cur[u] = i;
  208. }
  209. }
  210. gap[dep[u]]--;
  211. if (!gap[dep[u]]) return ans;
  212. dep[u] = Min + ;
  213. gap[dep[u]]++;
  214. if (u != st) u = edge[S[--top] ^ ].v;
  215. }
  216. return ans;
  217. }
  218.  
  219. int u[MAXM],v[MAXM],w[MAXM];
  220. int A,B,N,M;
  221. int main()
  222. {
  223. // freopen("sample.txt","r",stdin);
  224. int kase;
  225. scanf("%d",&kase);
  226. while (kase--)
  227. {
  228. scanf("%d%d",&N,&M);
  229. St.init(N);
  230. Ted.init(N);
  231. init();
  232. for (int i = ; i < M ; i++)
  233. {
  234. scanf("%d%d%d",&u[i],&v[i],&w[i]);
  235. St.add_edge(u[i],v[i],w[i],i + );
  236. //St.add_edge(v[i],u[i],w[i],i + 1);
  237. //Ted.add_edge(u[i],v[i],w[i],i + 1);
  238. Ted.add_edge(v[i],u[i],w[i],i + );
  239. }
  240. scanf("%d%d",&A,&B);
  241. St.dijkstra(A);
  242. /* if (St.dis[B] == INF)
  243. {
  244. puts("0");
  245. continue;
  246. }
  247. */
  248. Ted.dijkstra(B);
  249. for (int i = ; i < M ; i++)
  250. {
  251. int tu = u[i];
  252. int tv = v[i];
  253. int tw = w[i];
  254. if (tu == tv) continue;
  255. if ((St.dis[tu] + tw == St.dis[tv] && Ted.dis[tv] + tw == Ted.dis[tu])
  256. ||(St.dis[tv] + tw == St.dis[tu] && Ted.dis[tu] + tw == Ted.dis[tv]))
  257. {
  258. add_edge(tu,tv,);
  259. }
  260. }
  261. printf("%d\n",sap(A,B,N + ));
  262.  
  263. }
  264. return ;
  265. }

HDU 4370  0 or 1
看bin神题解吧。此题太神了。

这里代码主要记录一下如何求闭环。循环队列等问题

复制的

转换思维的题啊,由一道让人不知如何下手的题,转换为了最短路 基本思路就是把矩阵看做一个图,图中有n个点,1号点出度为1, n号点入度为1,其它点出度和入度相等,路径长度都是非负数,

等价于一条从1号节点到n号节点的路径,故Xij=1表示需要经 过边(i,j),代价为Cij。Xij=0表示不经过边(i,j)。注意到Cij非负 且题目要求总代价最小,因此最优答案的路径一定可以对应一条简单路径。

最终,我们直接读入边权的邻接矩阵,跑一次1到n的最短路即可,记最短路为path。

漏如下的情况B: 从1出发,走一个环(至少经过1个点,即不能 是自环),回到1;从n出发,走一个环(同理),回到n。 也就是1和n点的出度和入度都为1,其它点的出度和入度为0.

由于边权非负,于是两个环对应着两个简单环。

因此我们可以从1出发,找一个最小花费环,记代价为c1, 再从n出发,找一个最小花费环,记代价为c2。 (只需在最短路算法更新权值时多加一条记录即可:if(i==S) cir=min(cir,dis[u]+g[u][i]))

故最终答案为min(path,c1+c2) */ /* 本程序用SPFA来完成最短路。 但是由于要计算从出发点出发的闭环的路径长度。 所以要在普通SPFA的基础上做点变化。

就是把dist[start]设为INF。同时一开始并不是让出发点入队,而是让 出发点能够到达的点入队。

代码:

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int INF = 0x3f3f3f3f;
  24. int cost[MAXN][MAXN];
  25. int dist[MAXN];
  26. int que[MAXN];
  27. bool inq[MAXN];
  28.  
  29. void spfa(int s,int n)
  30. {
  31. int front = ,rear = ;
  32. for (int v = ; v <= n ; v++)
  33. {
  34. if (v == s)//由于要找start的闭环,所以dist[start]设为INF,且不入队
  35. {
  36. dist[v] = INF;
  37. inq[v] = false;
  38. }
  39. else if(cost[s][v] != INF)
  40. {
  41. dist[v] = cost[s][v];
  42. que[rear++] = v;
  43. inq[v] = true;
  44. }
  45. else//即dist[start][v]==INF情况,对本题没有这种情
  46. {
  47. dist[v] = INF;
  48. inq[v] = false;
  49. }
  50. }
  51. while (front != rear)//注意这个条件是不等,因为是循环队列
  52. {
  53. int u = que[front++];
  54. for (int v = ; v <= n ; v++)
  55. {
  56. if (dist[v] > dist[u] + cost[u][v])
  57. {
  58. dist[v] = dist[u] + cost[u][v];
  59. if (!inq[v])
  60. {
  61. que[rear++] = v;
  62. if (rear >= MAXN) rear = ;
  63. inq[v] = true;
  64. }
  65. }
  66. }
  67. inq[u] = false;
  68. if (front >= MAXN) front = ;
  69. }
  70.  
  71. }
  72.  
  73. int main()
  74. {
  75. int N;
  76. while (scanf("%d",&N) != EOF)
  77. {
  78. memset(cost,0x3f,sizeof(cost));
  79. for (int i = ; i <= N ; i++)
  80. for (int j = ; j <= N ; j++)
  81. scanf("%d",&cost[i][j]);
  82. spfa(,N);
  83. int ans = dist[N];//1到n的最短路
  84. int cmp = dist[];//1的自环长度
  85. spfa(N,N);
  86. cmp += dist[N];//N的自环长度
  87. printf("%d\n",min(ans,cmp));
  88. }
  89. return ;
  90. }

POJ 3169 Layout

查分约束变换一下不等式就行了

对那ML个条件

d[y] - d[x] <= w -> d[x] + w >= d[y]

对那MD个条件

d[y] - d[x] >= w -> d[y] + (-w) >= d[x]

对于一个不等式 d[u] + w >= d[v] 我们可以加边(u, v , w) 因为松弛操作

2份代码

  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const int INF = 0x3f3f3f3f;
  25. int N,ML,MD;
  26. bool inq[MAXN];
  27. int cnt[MAXN];
  28. struct Edge
  29. {
  30. int u,v,w;
  31. int next;
  32. }edge[MAXM];
  33. int head[MAXN],tot;
  34.  
  35. void init()
  36. {
  37. tot = ;
  38. memset(head,-,sizeof(head));
  39. }
  40.  
  41. void add_edge(int u,int v,int w)
  42. {
  43. edge[tot].u = u;
  44. edge[tot].v = v;
  45. edge[tot].w = w;
  46. edge[tot].next = head[u];
  47. head[u] = tot++;
  48. }
  49.  
  50. queue<int>q;
  51. int dis[MAXN];
  52.  
  53. bool spfa(int s,int n)
  54. {
  55. memset(inq,false,sizeof(inq));
  56. memset(cnt,,sizeof(cnt));
  57. memset(dis,0x3f,sizeof(dis));
  58. while(!q.empty()) q.pop();
  59. q.push(s);
  60. dis[s] = ;
  61. inq[s] = true;
  62. cnt[s] = ;
  63. while (!q.empty())
  64. {
  65. int u = q.front(); q.pop();
  66. inq[u] = false;
  67. //printf("%d %d\n",u,dis[u]);
  68. for (int i = head[u] ; i != - ; i = edge[i].next)
  69. {
  70. int v = edge[i].v;
  71. if (dis[v] > dis[u] + edge[i].w)
  72. {
  73. dis[v] = dis[u] + edge[i].w;
  74. if (!inq[v])
  75. {
  76. inq[v] = true;
  77. q.push(v);
  78. cnt[v]++;
  79. }
  80. if(cnt[v] >= n) return true;
  81. }
  82. }
  83. }
  84. return false;
  85. }
  86.  
  87. int main()
  88. {
  89. while (scanf("%d%d%d",&N,&ML,&MD) != EOF)
  90. {
  91. init();
  92. for (int i = ; i < ML ; i++)
  93. {
  94. int u,v,w;
  95. scanf("%d%d%d",&u,&v,&w);
  96. if(u > v) swap(u,v);
  97. add_edge(u,v,w);
  98. }
  99. for (int i = ; i < MD ; i++)
  100. {
  101. int u,v,w;
  102. scanf("%d%d%d",&u,&v,&w);
  103. if (u < v) swap(u,v);
  104. add_edge(u,v,-w);
  105. }
  106. // for (int i = 0 ; i < tot ; i++) printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].w);
  107. if (spfa(,N)) puts("-1");
  108. else if (dis[N] >= INF) puts("-2");
  109. else printf("%d\n",dis[N]);
  110. }
  111. return ;
  112. }
  1. #include <map>
  2. #include <set>
  3. #include <list>
  4. #include <cmath>
  5. #include <ctime>
  6. #include <deque>
  7. #include <stack>
  8. #include <queue>
  9. #include <cctype>
  10. #include <cstdio>
  11. #include <string>
  12. #include <vector>
  13. #include <climits>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <algorithm>
  18. #define LL long long
  19. #define PI 3.1415926535897932626
  20. using namespace std;
  21. int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
  22. const int MAXN = ;
  23. const int MAXM = ;
  24. const int INF = 0x3f3f3f3f;
  25. int N,ML,MD;
  26. int dis[MAXN];
  27. struct Edge
  28. {
  29. int u,v,w;
  30. int next;
  31. }edge[MAXM];
  32. int tot;
  33.  
  34. bool bellman_ford(int s,int n)
  35. {
  36. memset(dis,0x3f,sizeof(dis));
  37. dis[s] = ;
  38. for (int i = ; i <= n - ; i++)
  39. {
  40. for (int j = ; j < tot ; j++)
  41. {
  42. int u = edge[j].u;
  43. int v = edge[j].v;
  44. if (dis[v] > dis[u] + edge[j].w)
  45. {
  46. dis[v] = dis[u] + edge[j].w;
  47. }
  48. // printf("%d %d %d %d\n",u,v,dis[u],edge[j].w);
  49. }
  50. }
  51. for (int j = ; j < tot ; j++)
  52. {
  53. if (dis[edge[j].v] > dis[edge[j].u] + edge[j].w)
  54. return true;
  55. }
  56. return false;
  57. }
  58.  
  59. int main()
  60. {
  61. while (scanf("%d%d%d",&N,&ML,&MD) != EOF)
  62. {
  63. tot = ;
  64. for (int i = ; i < ML ; i++)
  65. {
  66. int u,v,w;
  67. scanf("%d%d%d",&u,&v,&w);
  68. if(u > v) swap(u,v);
  69. edge[tot].u = u;
  70. edge[tot].v = v;
  71. edge[tot].w = w;
  72. tot++;
  73. }
  74. for (int i = ; i < MD ; i++)
  75. {
  76. int u,v,w;
  77. scanf("%d%d%d",&u,&v,&w);
  78. if (u < v) swap(u,v);
  79. edge[tot].u = u;
  80. edge[tot].v = v;
  81. edge[tot].w = -w;
  82. tot++;
  83. }
  84. //for (int i = 0 ; i < tot ; i++) printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].w);
  85. if (bellman_ford(,N)) puts("-1");
  86. else if (dis[N] >= INF) puts("-2");
  87. else printf("%d\n",dis[N]);
  88. }
  89. return ;
  90. }

kuangbin带你飞 最短路 题解的更多相关文章

  1. 专题训练——[kuangbin带你飞]最短路练习

    最短路练习 0. Til the Cows Come Home  POJ - 2387 完美的模板题 //#include<Windows.h> #include<iostream& ...

  2. Kuangbin 带你飞 数位DP题解

    以前一直不知道该咋搞这个比较好. 感觉推起来那个数字好麻烦.后来有一种比较好的写法就是直接的DFS写法.相应的ismax表示当前位是否有限制. 数位DP也是有一种类似模版的东西,不过需要好好理解.与其 ...

  3. kuangbin带你飞 后缀数组 题解

    2份模板 DC3 . 空间复杂度O3N 时间复杂度On #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb)) #define G(x) ((x) < ...

  4. Dancing Links [Kuangbin带你飞] 模版及题解

    学习资料: http://www.cnblogs.com/grenet/p/3145800.html http://blog.csdn.net/mu399/article/details/762786 ...

  5. Tarjan 联通图 Kuangbin 带你飞 联通图题目及部分联通图题目

    Tarjan算法就不说了 想学看这 https://www.byvoid.com/blog/scc-tarjan/ https://www.byvoid.com/blog/biconnect/ 下面是 ...

  6. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

  7. KUANGBIN带你飞

    KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题    //201 ...

  8. 「kuangbin带你飞」专题二十 斜率DP

    layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...

  9. 「kuangbin带你飞」专题二十二 区间DP

    layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...

随机推荐

  1. 关于redis一些问题记录

    问题一:启动redis时出现警告,使用下列命令(已解决) 问题二:启动时,需要解决的警告(未解决) 问题三:使用自己的配置文件启动redis时,可能会遇到: Could not connect to ...

  2. 使用git创建分支

    Git大法好--3.Git分支本地操作详解 这时已经切换到了dingBranch分支下面了,在项目文件夹下添加一个dingBranchtest.txt文件,然后提交到本地仓库和远程仓库: git ad ...

  3. Mysql字符串截取:Left()、Right()、Substring()、Substring_index()

    在实际的项目开发中有时会有对数据库某字段截取部分的需求,这种场景有时直接通过数据库操作来实现比通过代码实现要更方便快捷些, mysql有很多字符串函数可以用来处理这些需求,如Mysql字符串截取总结: ...

  4. LINUX系统下Java和Scala的环境配置

    最近,笔者在研究一个有关“自然语言处理”的项目,在这个项目中,需要我们用Spark进行编程.而Spark内核是由Scala语言开发的,所以在使用Spark之前,我们必须配置好Scala,而Scala又 ...

  5. c++知识点总结--函数模板

    通用函数可变参模板 用于处理不限定参数的函数 showall(){//空函数,接口,最后结束递归 } template<typename T,typename... Args> void ...

  6. Python3 初识Python

    一 Python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC ...

  7. lubuntu 使用USB摄像头

    http://liangbing8612.blog.51cto.com/2633208/598762 Most of the camera driver has integrated in the k ...

  8. 有关parent.frame.cols在firefox浏览器上不兼容的问题解决

    IE(不兼容FireFox): if(parent.myFrame.cols == "199,7,*") { parent.myFrame.cols="0,7,*&quo ...

  9. Node js 安装+回调函数+事件

    /* 从网站 https://nodejs.org/zh-cn/ 下载 这里用的 9.4.0 版本 下载完安装 安装目录是 D:\ApacheServer\node 一路默认安装 安装后打开cmd命令 ...

  10. mysql 数据包太小会引发错误信息

    Error querying database.  Cause: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for quer ...