经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
[分层图最短路][学习笔记]
来源:cnblogs  作者:wxyww  时间:2018/12/17 9:47:41  对本文有异议

昨天考试分层图最短路用个dp暴力水了90分。今天只有10分。。。还是好好来学分层图吧。(实际是不想学数据结构2333)

一类问题

分层图最短路得经典模板题就是这样

给出一个n个点m条边的无向图,每条边有边权,可以选择最多k条边,把他们的边权变为0。问从S到T的最短路是多少。

解法

一般这类问题K都会比较小。所以可以建K层图。第i层图表示已经把i条边变成0。

然后就是怎么连边。首先在每层图中,u和v之间还是要连边的。那么两层图之间的边呢。为了表示出已经把一条边变为0了,所以要把第i - 1层图中的u向第i层中的v连一条权值为0的边,因为是无向图。所以还要把第i - 1层中的v向第i层中的u连一条权值为0的边。

一些细节

那么怎么来表示这个点是第几层图中的呢??

有一个非常经典的做法。就是把第i层图中的j号点的编号记为i * n +j。这样就可以保证每层图中节点的标号都不一样,并且还可以准确找到每层图的每个节点。

为啥不挂图?

题面

一条道路移动到另一条道路之类的时间,只计算他在这些道路上花费的时间总和。

除此之外,小喵喵还有k个时间暂停器,每个可以使某一条道路的经过时间变为0.

【输入格式】

第1行三个整数n,m,k,表示路口个数,道路的数量,时间暂停器的数量。

第2~m+1行每行三个整数u[i],v[i],c[i],表示u[i]和v[i]之间有一条可以双向通行的道路,通过所需时间为c[i]。

【输出格式】

一个整数,表示小喵喵所需的最短时间。

【样例输入输出】

5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2 3

【样例解释】

小喵喵选择从1->3->4->5,并且在1->3的道路上使用时间暂停器。

总耗时为0+1+2=3.

【数据范围】

对于20%的数据,n<=5,m<=10.

对于另外20%的数据,k=0.

对于另外30%的数据,k=1.

对于所有的数据,n<=1000,m<=10000,k<=10,c[i]<=109,保证存在从1号路口到n号路口的路径。注意,可能存在两条道路的起点和终点组成的集合相同,也可能存在起点和终点是相同路口的道路。

代码

  1. /*
  2. * @Author: wxyww
  3. * @Date: 2018-12-15 15:10:24
  4. * @Last Modified time: 2018-12-15 17:27:21
  5. */
  6. #include<cstdio>
  7. #include<iostream>
  8. #include<queue>
  9. #include<cstring>
  10. #include<cstdlib>
  11. #include<cmath>
  12. #include<ctime>
  13. #include<bitset>
  14. using namespace std;
  15. typedef long long ll;
  16. const int N = 100000 + 100;
  17. const ll INF = 1e14;
  18. ll read() {
  19. ll x=0,f=1;char c=getchar();
  20. while(c<'0'||c>'9') {
  21. if(c=='-') f=-1;
  22. c=getchar();
  23. }
  24. while(c>='0'&&c<='9') {
  25. x=x*10+c-'0';
  26. c=getchar();
  27. }
  28. return x*f;
  29. }
  30. struct node {
  31. int v,nxt,w;
  32. }e[N * 20];
  33. int n,m,K;
  34. int head[N],ejs;
  35. void add(int u,int v,int w) {
  36. e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w;
  37. }
  38. ll dis[N * 20];
  39. queue<int>q;
  40. int vis[N];
  41. void spfa() {
  42. q.push(1);
  43. while(!q.empty()) {
  44. int u = q.front();q.pop();
  45. vis[u] = 0;
  46. for(int i = head[u];i;i = e[i].nxt) {
  47. int v = e[i].v;
  48. if(dis[v] > dis[u] + e[i].w) {
  49. dis[v] = dis[u] + e[i].w;
  50. if(!vis[v]) {
  51. vis[v] = 1;
  52. q.push(v);
  53. }
  54. }
  55. }
  56. }
  57. }
  58. int main() {
  59. n = read(),m = read(),K = read();
  60. for(int i = 1;i <= m;++i) {
  61. int u = read(),v = read(),w = read();
  62. add(u,v,w);
  63. add(v,u,w);
  64. for(int j = 1;j <= K;++j) {
  65. add(j * n + u,j * n + v,w);
  66. add(j * n + v,j * n + u,w);
  67. add((j - 1) * n + u,j * n + v,0);
  68. add((j - 1) * n + v,j * n + u,0);
  69. }
  70. }
  71. for(int i = 0;i <= n * K + n;++i) dis[i] = INF;
  72. dis[1] = 0;
  73. spfa();
  74. ll ans = dis[n];
  75. for(int i = 0;i <= K;++i) ans = min(ans,dis[i * n + n]);
  76. cout<<ans;
  77. return 0;
  78. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号