最短路练习

0. Til the Cows Come Home  POJ - 2387

完美的模板题

  1. //#include<Windows.h>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cstdio>
  6. #include<queue>
  7. using namespace std;
  8. const int MAX_V = ;
  9. const int MAX_E = ;
  10. const int inf = 0x3f3f3f3f;
  11.  
  12. struct ENode
  13. {
  14. int to;
  15. int Next;
  16. int w;
  17. };
  18. ENode Edegs[MAX_E];
  19. int Head[MAX_V];
  20. int Dis[MAX_V];
  21. int tnt;
  22. void Add_ENode(int u, int v, int w)
  23. {
  24. ++tnt;
  25. Edegs[tnt].to = v;
  26. Edegs[tnt].w = w;
  27. Edegs[tnt].Next = Head[u];
  28. Head[u] = tnt;
  29. ++tnt;
  30. Edegs[tnt].to = u;
  31. Edegs[tnt].w = w;
  32. Edegs[tnt].Next = Head[v];
  33. Head[v] = tnt;
  34. }
  35. struct cmpx
  36. {
  37. bool operator () (int &a, int &b) const
  38. {
  39. return Dis[a] - Dis[b] > ;
  40. }
  41. };
  42.  
  43. void Dijkstra(int x)
  44. {
  45. priority_queue<int, vector<int>, cmpx> q;
  46. memset(Dis, inf, sizeof(Dis));
  47. Dis[x] = ;
  48. q.push(x);
  49. while (!q.empty())
  50. {
  51. int u = q.top();
  52. q.pop();
  53. for (int k = Head[u]; k != -; k= Edegs[k].Next)
  54. {
  55. int v = Edegs[k].to;
  56. if (Dis[v] > Dis[u] + Edegs[k].w)
  57. {
  58. Dis[v] = Dis[u] + Edegs[k].w;
  59. q.push(v);
  60. }
  61. }
  62. }
  63. }
  64.  
  65. int main()
  66. {
  67. int t, n;
  68. cin >> t >> n;
  69. tnt = -;
  70. int a, b, w;
  71. memset(Head, -, sizeof(Head));
  72. for (int i = ; i < t; i++)
  73. {
  74. cin >> a >> b >> w;
  75. Add_ENode(a, b, w);
  76. }
  77. Dijkstra();
  78. cout << Dis[n] << endl;
  79. // system("pause");
  80. return ;
  81. }

1. Frogger POJ - 2253

青蛙和石头。在池塘里有2只青蛙和n块石头,石头之间有一定距离,现在一只(腿短的)青蛙想要去找另一只青蛙yuehui;给出n块石头的坐标,1号为男主青蛙所在的石头,二号为目标石头。他想尽可能的省力,每次都跳的尽量短。问它在所有可行路径中单次跳跃需要的最长距离的最小值是多少?

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<cmath>
  7. using namespace std;
  8. const int MAX_V= ;
  9. const double inf= 99999999999999999.0;
  10. typedef pair<double, double> _pair;
  11. _pair rock[MAX_V];
  12. double get_dis(_pair a, _pair b)
  13. {
  14. return sqrt(((a.first- b.first)* (a.first- b.first) )+ ((a.second- b.second)* (a.second- b.second) ) );
  15. }
  16. double Dis[MAX_V];
  17. struct cmpx
  18. {
  19. bool operator() (int &a, int &b) const
  20. {
  21. return Dis[a]- Dis[b]> ;
  22. }
  23. };
  24. int Front[MAX_V];
  25. void Dijkstra(int n)
  26. {
  27. priority_queue<int, vector<int>, cmpx> q;
  28. fill(Dis, Dis+ n+ , inf);
  29. //for(int i= 1; i<= n; i ++) printf("%f\n", Dis[2]);
  30. Dis[]= ;
  31. Front[]= -;
  32. q.push();
  33. while (! q.empty() )
  34. {
  35. int u= q.top();
  36. q.pop();
  37. for (int i= ; i<= n; i ++)
  38. {
  39. if (i== u) continue;
  40. double detmp= get_dis(rock[u], rock[i]);
  41. //printf("%f---%f---%f\n", Dis[u], detmp, Dis[i]);
  42. if (Dis[i]> Dis[u]&& Dis[i]> detmp)
  43. {
  44. Dis[i]= max(Dis[u], detmp);
  45. Front[i]= u;
  46. q.push(i);
  47. }
  48. //printf("%f\n", Dis[i]);
  49. }
  50. }
  51. }
  52. int main()
  53. {
  54. int n;
  55. int t= ;
  56. while (cin >> n)
  57. {
  58. ++ t;
  59. if (n== ) break;
  60. for (int i= ; i<= n; i ++)
  61. {
  62. cin >> rock[i].first >> rock[i].second;
  63. }
  64. //for(int i= 2; i<= n; i ++) printf("%f\n", get_dis(rock[1], rock[i]));
  65. Dijkstra(n);
  66. printf("Scenario #%d\n",t);
  67. printf("Frog Distance = %.3f\n\n", Dis[]);
  68. double ans= -1.0;
  69. /*for (int c= n; c!= 1; c= Front[c])
  70. {
  71. double cnp= get_dis(rock[c], rock[Front[c]]);
  72. ans= max(ans, cnp);
  73. }
  74. printf("Frog Distance = %.3f\n\n", ans);*/
  75. }
  76. return ;
  77. }

2. Heavy Transportation POJ - 1797

城市中有N个路口,M个街道,每条街道都有最大承重限制;现在我们想要驾车从1号路口到N号路口,那么运输车所允许的最大重量是多少?

(不知道为什么老是PE,懒得改了)

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. using namespace std;
  7. const int maxv= ;
  8. const int maxe= ;
  9. const int inf= 0x3f3f3f3f;
  10.  
  11. struct ENode
  12. {
  13. int to;
  14. int w;
  15. int Next;
  16. };
  17. ENode edegs[maxe];
  18. int Head[maxv], tnt;
  19. void init()
  20. {
  21. memset(Head, -, sizeof(Head));
  22. tnt= -;
  23. }
  24. void Add_ENode(int a, int b, int w)
  25. {
  26. ++ tnt;
  27. edegs[tnt].to= b;
  28. edegs[tnt].w= w;
  29. edegs[tnt].Next= Head[a];
  30. Head[a]= tnt;
  31. ++ tnt;
  32. edegs[tnt].to= a;
  33. edegs[tnt].w= w;
  34. edegs[tnt].Next= Head[b];
  35. Head[b]= tnt;
  36. }
  37.  
  38. int dis[maxv];
  39. struct cmpx
  40. {
  41. bool operator() (int &a, int &b) const
  42. {
  43. return dis[a]- dis[b]< ;
  44. }
  45. };
  46. void Dijkstra(int x)
  47. {
  48. priority_queue<int, vector<int>, cmpx> q;
  49. memset(dis, , sizeof(dis));
  50. dis[x]= inf;
  51. q.push(x);
  52.  
  53. while (! q.empty())
  54. {
  55. int u= q.top();
  56. q.pop();
  57. for (int k= Head[u]; k!= -; k= edegs[k].Next)
  58. {
  59. int v= edegs[k].to;
  60. if (dis[v]< min(dis[u], edegs[k].w))
  61. {
  62. dis[v]= min(dis[u], edegs[k].w);
  63. q.push(v);
  64. }
  65. }
  66. }
  67. }
  68.  
  69. int main()
  70. {
  71. int t, Case= ;
  72. int n, m;
  73. scanf("%d", &t);
  74. while (t --)
  75. {
  76. ++ Case;
  77. scanf("%d %d", &n, &m);
  78. init();
  79. int a, b, w;
  80. for (int i= ; i< m; i ++)
  81. {
  82. scanf("%d %d %d", &a, &b, &w);
  83. Add_ENode(a, b, w);
  84. }
  85. Dijkstra();
  86. printf("Scenario #%d:\n%d\n", Case, dis[n]);
  87. }
  88. return ;
  89. }

3. Travel (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M)  /**计蒜客复现赛:点这里*/

星系中有n 个星球,编号从1 到N。星球之间有M个隧道相连,每个隧道都有一个长度。你有一个航天器,航天器有两个属性:传输距离d 和传输次数e 。航天器只能通过短于或等于其传输距离的通道;如果传输次数耗尽,则无法再使用航天器。航天器具有等级,lv0的航天器d 和e 都等于0,你可以给你的航天器升级,每次升级都会消耗c 点花费,给你的航天器提升dx和 ex点属性。现在,告诉你n,m,m条通道的信息,还有给你的航天器升级时的c,dx,ex。

Q: 你能求出从1 到N 的最小花费吗?

A: 把原本记录到达此点最短距离的Dis[] 变成 记录到达此点所需要飞行器最低等级的Dis_Level[],这样剩下的就是普通的Dijkstra了。

  1. #include<algorithm>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<queue>
  5. using namespace std;
  6. const int MAX_V= ;
  7. const int MAX_E= ;
  8. const int inf= 0x3f3f3f3f;
  9.  
  10. struct ENode
  11. {
  12. int to;
  13. int w;
  14. int Next;
  15. };
  16. ENode edegs[MAX_E];
  17. int Head[MAX_V], tnt;
  18. void Add_ENode(int a, int b, int w)
  19. {
  20. edegs[++ tnt].to= b;
  21. edegs[tnt].w= w;
  22. edegs[tnt].Next= Head[a];
  23. Head[a]= tnt;
  24. edegs[++ tnt].to= a;
  25. edegs[tnt].w= w;
  26. edegs[tnt].Next= Head[b];
  27. Head[b]= tnt;
  28. }
  29.  
  30. int Dis_Level[MAX_V]; //到每个点,所需要的飞船最小等级;
  31. int deep[MAX_V]; //每个点bfs 的深度;
  32. struct cmpx
  33. {
  34. bool operator() (int &a, int &b) const
  35. {
  36. return Dis_Level[a]- Dis_Level[b]> ;
  37. }
  38. };
  39. void Dijkstra(int x, int _dis, int _cost)
  40. {
  41. /*x为起点, _dis是每次升级提升的传送距离, _cost是升级提升的传送次数;*/
  42. memset(Dis_Level, inf, sizeof(Dis_Level));
  43. memset(deep, inf, sizeof(deep));
  44. priority_queue<int, vector<int>, cmpx> q;
  45. Dis_Level[x]= ; //起点的飞行器等级为0;
  46. deep[x]= ; //起点深度为0;
  47. q.push(x);
  48. while (! q.empty())
  49. {
  50. int u= q.top();
  51. q.pop();
  52. for (int k= Head[u]; k!= -; k= edegs[k].Next)
  53. {
  54. int v= edegs[k].to;
  55. int lev_tmp= Dis_Level[u];
  56. while (lev_tmp* _dis< edegs[k].w|| lev_tmp* _cost< deep[u]+ )
  57. {
  58. /*若当前的飞行器等级不能穿越此隧道,或传送次数已用完,则升级飞行器一次;*/
  59. lev_tmp ++;
  60. }
  61. if (lev_tmp< Dis_Level[v])
  62. {
  63. /*如果此时的飞行器等级小与之前到达点v 的飞行器等级,则更新Dis_Level[v]*/
  64. Dis_Level[v]= lev_tmp;
  65. deep[v]= deep[u]+ ; //深度也要 +1;
  66. q.push(v); //加入队列;
  67. }
  68. }
  69. }
  70. }
  71. void into()
  72. {
  73. memset(Head, -, sizeof(Head));
  74. tnt= -;
  75. }
  76.  
  77. int main()
  78. {
  79. int n, m;
  80. int c, d, e;
  81. int a, b ,w;
  82. while (~ scanf("%d %d", &n, &m))
  83. {
  84. scanf("%d %d %d", &c, &d, &e);
  85. into();
  86. for (int i= ;i< m;i ++)
  87. {
  88. scanf("%d %d %d", &a, &b, &w);
  89. Add_ENode(a, b, w);
  90. }
  91. Dijkstra(, d, e);
  92. if (Dis_Level[n]== inf) printf("-1\n");
  93. else printf("%lld\n", (long long)Dis_Level[n]* c);
  94. }
  95. return ;
  96. }

4.Marriage Match IV (HDU 3416)

Starvae在A市,女孩在B市。每次starvae都可以到达B市并与他喜欢的女孩一起xoxo。但是他面前有两个问题,一是starvae必须在最短的时间内到达B,所以说他必须选择最短的路径;二是每条道路只能走一次,但每座城市他可以经过多次。那么,请你告诉他:从A-->B的(完全不同的)最短路径一共有几条?

Ps:最短路径+最大流。先用Dijkstra求出A到B的最短路径并处理dis[]数组,然后依照条件(dis[v]== dis[u]+ edegs[k].w)找出所有在最短路径上的边,并建一个图2。随后就是Dinic跑最大流出结果,代码如下。

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. using namespace std;
  7. const int maxv= ;
  8. const int maxe= ;
  9. const int inf= 0x3f3f3f3f;
  10.  
  11. struct ENode
  12. {
  13. int to;
  14. int w;
  15. int Next;
  16. };
  17. ENode edegs[maxe];
  18. int Head[maxv], tnt;
  19. void init()
  20. {
  21. memset(Head, -, sizeof(Head));
  22. tnt= -;
  23. }
  24. void Add_ENode(int a, int b, int w)
  25. {
  26. ++ tnt;
  27. edegs[tnt].to= b;
  28. edegs[tnt].w= w;
  29. edegs[tnt].Next= Head[a];
  30. Head[a]= tnt;
  31. }
  32.  
  33. int dis[maxv];
  34. struct cmpx
  35. {
  36. bool operator() (int &a, int &b) const
  37. {
  38. return dis[a]- dis[b]> ;
  39. }
  40. };
  41. void Dijkstra(int x)
  42. {
  43. priority_queue<int, vector<int>, cmpx> q;
  44. memset(dis, inf, sizeof(dis));
  45. dis[x]= ;
  46. q.push(x);
  47.  
  48. while (! q.empty())
  49. {
  50. int u= q.top();
  51. q.pop();
  52.  
  53. for (int k= Head[u]; k!= -; k= edegs[k].Next)
  54. {
  55. int v= edegs[k].to;
  56. if (dis[v]> dis[u]+ edegs[k].w )
  57. {
  58. dis[v]= dis[u]+ edegs[k].w;
  59. q.push(v);
  60. }
  61. }
  62. }
  63. }
  64.  
  65. /*建新图,跑最大流*/
  66. ENode edegs1[maxe];
  67. int Head1[maxv], tnt1;
  68. void init1()
  69. {
  70. memset(Head1, -, sizeof(Head1));
  71. tnt1= -;
  72. }
  73. void Add_ENode1(int a, int b, int w)
  74. {
  75. ++ tnt1;
  76. edegs1[tnt1].to= b;
  77. edegs1[tnt1].w= w;
  78. edegs1[tnt1].Next= Head1[a];
  79. Head1[a]= tnt1;
  80. ++ tnt1;
  81. edegs1[tnt1].to= a;
  82. edegs1[tnt1].w= ;
  83. edegs1[tnt1].Next= Head1[b];
  84. Head1[b]= tnt1;
  85. }
  86. void Dijk2(int n)
  87. {
  88. init1();
  89. for (int u= ; u<= n; u ++)
  90. {
  91. for (int k= Head[u]; k!= -; k= edegs[k].Next)
  92. {
  93. int v= edegs[k].to;
  94. if (dis[v]== dis[u]+ edegs[k].w )
  95. {
  96. Add_ENode1(u, v, );
  97. }
  98. }
  99. }
  100. }
  101. int level[maxv];
  102. bool bfs_level (int s, int t)
  103. {
  104. memset(level, -, sizeof(level)); //所有点的等级初始化为-1;
  105. level[s]= ; //源点的等级为1;
  106. int que[maxv]; //队列que:按序保存已搜索到的点;
  107. int iq= ;
  108. que[iq ++]= s; //先将源点s 加入队列;
  109. for (int i= ; i< iq; i ++)
  110. {
  111. int u= que[i]; //取出队首元素;
  112. if (u== t)
  113. {
  114. /*找到汇点t,返回*/
  115. return true;
  116. }
  117. for (int k= Head1[u]; k!= -; k= edegs1[k].Next)
  118. {
  119. /*遍历,查找到之前未找到的、可抵达的点便加入队列*/
  120. int v= edegs1[k].to;
  121. if (-== level[v]&& edegs1[k].w)
  122. {
  123. level[v]= level[u]+ ; //深度 +1;
  124. que[iq ++]= v;
  125. }
  126. }
  127. }
  128. return false;
  129. }
  130. int dfs(int now, int c_max, int t)
  131. {
  132. /**DFS 实现多路增广*/
  133. /*now:起点;c_max:从源点s到节点now的最大流量;t:汇点、dfs结束的终点*/
  134. if (now== t) return c_max; //当now== t时,c_max便是要求的最大流;
  135. int ret= , f;
  136. for (int k= Head1[now]; k!= -; k= edegs1[k].Next)
  137. {
  138. if (edegs1[k].w&& level[edegs1[k] .to]== level[now]+ )
  139. {
  140. /**/
  141. f= dfs(edegs1[k].to, min(c_max- ret, edegs1[k].w), t);
  142. edegs1[k].w-= f;
  143. edegs1[k^].w+= f;
  144. ret+= f;
  145. if(ret== c_max) return ret;
  146. }
  147. }
  148. return ret;
  149. }
  150. int dinic(int s, int t)
  151. {
  152. int ans= ;
  153. while(bfs_level(s, t))
  154. {
  155. ans+= dfs(s, inf, t);
  156. }
  157. return ans;
  158. }
  159.  
  160. int main()
  161. {
  162. int t;
  163. int n, m;
  164. scanf("%d", &t);
  165. while (t --)
  166. {
  167. scanf("%d %d", &n, &m);
  168. init();
  169. int a, b, w;
  170. for (int i= ; i< m; i ++)
  171. {
  172. scanf("%d %d %d", &a, &b, &w);
  173. Add_ENode(a, b, w);
  174. }
  175. int start, endd;
  176. scanf("%d %d", &start, &endd);
  177. Dijkstra(start);
  178. Dijk2(n);
  179. int ans= dinic(start, endd);
  180. printf("%d\n", ans);
  181. }
  182. return ;
  183. }

end;

专题训练——[kuangbin带你飞]最短路练习的更多相关文章

  1. kuangbin带你飞 最短路 题解

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

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

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

  3. [kuangbin带你飞]专题1-23题目清单总结

    [kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...

  4. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  5. 「kuangbin带你飞」专题十四 数论基础

    layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...

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

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

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

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

  8. 「kuangbin带你飞」专题十九 矩阵

    layout: post title: 「kuangbin带你飞」专题十九 矩阵 author: "luowentaoaa" catalog: true tags: mathjax ...

  9. 「kuangbin带你飞」专题十八 后缀数组

    layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kua ...

随机推荐

  1. mysql 状态查询

    select  COUNT(case when info.State = '0' then State end  ) as daichuliCount, COUNT(case when info.St ...

  2. VirtualBox搭建1主2从虚拟机

    环境要求 最近在使用VirtualBox搭建一个实验环境,由于公司规定了所有的机器都不能使用固定IP,都必须由DHCP自动获取. 为了不影响公司整理的网络环境,只能把实验用的网络环境限制在使用内部IP ...

  3. Python函数缓存

    函数缓存 (Function caching) 函数缓存允许我们将一个函数对于给定参数的返回值缓存起来.当一个I/O密集的函数被频繁使用相同的参数调用的时候,函数缓存可以节约时间.在Python 3. ...

  4. [Usaco2005 Jan]Muddy Fields泥泞的牧场

    Description 雨连续不断的击打了放牛的牧场,一个R行C列的格子(1<=R<=50,1<=C<=50).虽然这对草来说是件好事,但这却使得一些没有草遮盖的土地变得很泥泞 ...

  5. 洛谷 P2742 [USACO5.1]圈奶牛Fencing the Cows || 凸包模板

    整篇都是仅做记录... 蓝书上的板子.水平序,单调栈.先求下凸包,再求上凸包.叉积的作用是判定向量的位置关系. 48行的作用是在求上凸包的时候不至于去删下凸包中的点.上凸包中第一个点被认为是t1. 另 ...

  6. 415 Add Strings 字符串相加

    给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和.注意:    num1 和num2 的长度都小于 5100.    num1 和num2 都只包含数字 0-9.    num1 和 ...

  7. ES6知识点汇总

    MDN镇楼: https://developer.mozilla.org/zh-CN/ 1.ES6新添加数据类型:symbol  -----------   https://developer.moz ...

  8. redis的安装使用以及一些常用的命令

    Redis是一个key-value存储系统.并提供多种语言的API,我们可使用它构建高性能,可扩展的Web应用程序.目前越来越多的网站用它来当做缓存,减轻服务器的压力. 本文安装用的到redis是绿色 ...

  9. AJPFX总结面向对象特征之一的继承知识

    继 承(面向对象特征之一) 好处: 1:提高了代码的复用性. 2:让类与类之间产生了关系,提供了另一个特征多态的前提.   父类的由来:其实是由多个类不断向上抽取共性内容而来的. java中对于继承, ...

  10. CF792C Divide by Three

    思路: dp. 实现: #include <iostream> #include <cstdio> #include <cstring> #include < ...