CF715B. Complete The Graph

题意:

给一张 n 个点,m 条边的无向图,要求设定一些边的边权

使得所有边权都是正整数,最终 S 到 T 的最短路为 L

1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000


假做法:

spfa求s到t最短路且满足可变边最少

然后把不在最短路上的可变边标为inf,最短路上的可变边修改成使最短路长为L

假的原因:

其他的赋值为inf只是保证了经过其他可变边的路径不会更短,没有保证不经过其他可变边只是少经过了几条可变边、导致比最短路长的路径不会在最短路修改后更短

存在绕过某条可变边的路径p,本来不是最短路且不经过最短路上可变边x,但你修改x之后,p会变成当前最短路,于是这个做法就挂掉了。

就是说走了非可变边,把你修改的那条可变边绕过去了

修正:

真做法1:

应当选择满足d<L的路径中经过可变边最少的一条

可以在最短路上加维,\(d(i,j)\)表示1到i经过j条可变边的最短路

复杂度\(O(mn\log{mn})\)

真做法2:

随便求一条最短路,同样其他赋值inf,然后枚举最短路上的可变边,依次修改改可变边的值,修改后再求最短路看看会不会被绕过去。最后一定会收敛出答案

无解:不经过可变边就可以<L,经过可变边也比L大

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <queue>
  6. #include <vector>
  7. using namespace std;
  8. typedef long long ll;
  9. const int N = 1e5+5, M = 1e6+5;
  10. const ll inf = 1e16;
  11. int n, m, L, s, t;
  12. struct edge {int u, v, ne; ll w;} e[M];
  13. struct meow {int u, v; ll w;} a[M];
  14. int cnt=1, h[N], mark[M];
  15. inline void ins(int u, int v, ll w) {
  16. if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1;
  17. e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt;
  18. e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt;
  19. a[cnt>>1] = (meow) {u, v, w};
  20. }
  21. inline void paint(int x, ll v) {
  22. a[x].w = v;
  23. e[x<<1].w = e[x<<1|1].w = v;
  24. }
  25. ll d[N];
  26. int inq[N], pre[N];
  27. int q[N], head, tail;
  28. inline void lop(int &x) {if(x==N) x = 1;}
  29. void spfa0(int s) {
  30. memset(d, 0x3f, sizeof(d));
  31. head = tail = 1;
  32. d[s] = 0; q[tail++] = s; inq[s] = 1;
  33. while(head != tail) {
  34. int u = q[head++]; lop(head); inq[u] = 0;
  35. for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) {
  36. int v = e[i].v;
  37. if(d[v] > d[u] + e[i].w) {
  38. d[v] = d[u] + e[i].w;
  39. if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
  40. }
  41. }
  42. }
  43. }
  44. void spfa(int s) {
  45. memset(d, 0x3f, sizeof(d));
  46. memset(inq, 0, sizeof(inq));
  47. head = tail = 1;
  48. d[s] = 0; q[tail++] = s; inq[s] = 1;
  49. while(head != tail) {
  50. int u = q[head++]; lop(head); inq[u] = 0;
  51. for(int i=h[u]; i; i=e[i].ne) {
  52. int v = e[i].v;
  53. if(d[v] > d[u] + e[i].w ) {
  54. d[v] = d[u] + e[i].w;
  55. pre[v] = i;
  56. if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
  57. }
  58. }
  59. }
  60. }
  61. int chose[N];
  62. vector<int> li;
  63. int main() {
  64. //freopen("in", "r", stdin);
  65. ios::sync_with_stdio(false); cin.tie(); cout.tie();
  66. cin >> n >> m >> L >> s >> t;
  67. s++; t++;
  68. for(int i=1; i<=m; i++) {
  69. int u, v, w;
  70. cin >> u >> v >> w;
  71. u++; v++;
  72. ins(u, v, w);
  73. }
  74. spfa0(s);
  75. if(d[t] < L) {cout << "NO"; return 0;}
  76. spfa(s);
  77. if(d[t] > L) {cout << "NO"; return 0;}
  78. if(d[t] == L) {
  79. cout << "YES" << endl;
  80. for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
  81. return 0;
  82. }
  83. int x = t;
  84. while(x != s) {
  85. if(mark[pre[x]]) chose[pre[x]>>1] = 1, li.push_back(pre[x]>>1);
  86. x = e[pre[x]].u;
  87. }
  88. for(int i=1; i<=cnt>>1; i++) if(mark[i<<1] && !chose[i]) paint(i, inf);
  89. for(int i=0; i<li.size(); i++) {
  90. int now = li[i];
  91. int delta = L - d[t] + 1;
  92. paint(now, delta);
  93. spfa(s);
  94. if(d[t] == L) break;
  95. }
  96. cout << "YES" << endl;
  97. for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
  98. }

ps:假做法的代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <queue>
  6. using namespace std;
  7. typedef long long ll;
  8. const int N = 1e5+5, M = 1e6+5;
  9. const ll inf = 1e16;
  10. int n, m, L, s, t;
  11. struct edge {int u, v, ne; ll w;} e[M];
  12. struct meow {int u, v; ll w;} a[M];
  13. int cnt=1, h[N], mark[M];
  14. inline void ins(int u, int v, ll w) {
  15. if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1;
  16. e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt;
  17. e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt;
  18. a[cnt>>1] = (meow) {u, v, w};
  19. }
  20. ll d[N];
  21. int inq[N], cou[N], pre[N];
  22. int q[N], head, tail;
  23. inline void lop(int &x) {if(x==N) x = 1;}
  24. void spfa0(int s) {
  25. memset(d, 0x3f, sizeof(d));
  26. head = tail = 1;
  27. d[s] = 0; q[tail++] = s; inq[s] = 1;
  28. while(head != tail) {
  29. int u = q[head++]; lop(head); inq[u] = 0;
  30. for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) {
  31. int v = e[i].v;
  32. if(d[v] > d[u] + e[i].w) {
  33. d[v] = d[u] + e[i].w;
  34. if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
  35. }
  36. }
  37. }
  38. }
  39. namespace test {
  40. int pre[N];
  41. void spfa1(int s) {
  42. memset(d, 0x3f, sizeof(d));
  43. head = tail = 1;
  44. d[s] = 0; q[tail++] = s; inq[s] = 1;
  45. while(head != tail) {
  46. int u = q[head++]; lop(head); inq[u] = 0;
  47. for(int i=h[u]; i; i=e[i].ne) {
  48. int v = e[i].v;
  49. if(d[v] > d[u] + e[i].w) {
  50. d[v] = d[u] + e[i].w;
  51. pre[v] = i;
  52. if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
  53. }
  54. }
  55. }
  56. }
  57. }
  58. void spfa(int s) {
  59. memset(d, 0x3f, sizeof(d));
  60. memset(cou, 0x3f, sizeof(cou));
  61. memset(inq, 0, sizeof(inq));
  62. head = tail = 1;
  63. d[s] = 0; cou[s] = 0; q[tail++] = s; inq[s] = 1;
  64. while(head != tail) {
  65. int u = q[head++]; lop(head); inq[u] = 0;
  66. for(int i=h[u]; i; i=e[i].ne) {
  67. int v = e[i].v;
  68. if(d[v] > d[u] + e[i].w || (d[v] == d[u]+e[i].w && cou[v] > cou[u] + mark[i])) {
  69. d[v] = d[u] + e[i].w;
  70. cou[v] = cou[u] + mark[i];
  71. pre[v] = i;
  72. if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
  73. }
  74. }
  75. }
  76. }
  77. int chose[N];
  78. int main() {
  79. //freopen("in", "r", stdin);
  80. ios::sync_with_stdio(false); cin.tie(); cout.tie();
  81. cin >> n >> m >> L >> s >> t;
  82. s++; t++;
  83. for(int i=1; i<=m; i++) {
  84. int u, v, w;
  85. cin >> u >> v >> w;
  86. u++; v++;
  87. ins(u, v, w);
  88. }
  89. spfa0(s);
  90. if(d[t] < L) {cout << "NO"; return 0;}
  91. spfa(s);
  92. if(d[t] > L) {cout << "NO"; return 0;}
  93. if(d[t] == L) {
  94. cout << "YES" << endl;
  95. for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
  96. return 0;
  97. }
  98. int x = t;
  99. int flag = 0;
  100. while(x != s) {
  101. if(mark[pre[x]]) chose[pre[x]>>1] = 1, flag = pre[x] >> 1;
  102. x = e[pre[x]].u;
  103. }
  104. if(!flag) {cout << "NO"; return 0;}
  105. for(int i=1; i <= cnt>>1; i++) if(mark[i<<1] && !chose[i]) a[i].w = inf;
  106. for(int i=1; i<=cnt; i++) if(mark[i] && !chose[i>>1]) e[i].w = inf;
  107. int delta = L - d[t] + 1;
  108. a[flag].w = delta;
  109. e[flag<<1].w = e[flag<<1|1].w = delta;
  110. test::spfa1(s);
  111. if(d[t] != L) {
  112. cout << d[t] << "nooooo\n";
  113. int x = t;
  114. while(x != s) {
  115. if(test::pre[x] != pre[x]) {
  116. cout << "wrong\n";
  117. cout << mark[pre[x]] << " " << mark[test::pre[x]] << '\n';
  118. }
  119. x = e[pre[x]].u;
  120. }
  121. }
  122. cout << "YES" << endl;
  123. for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
  124. }

CF715B. Complete The Graph的更多相关文章

  1. 【图论 思维】cf715B. Complete The Graph加强

    zzq讲的杂题 题目大意 有一张$n​$个点$m​$条边的简单正权无向图,$S​$到$T​$的最短路为$L​$,现在有一些边的边权未知,请输出任意一种满足题意的方案. $n,m\le 500000​$ ...

  2. Codeforces 715B & 716D Complete The Graph 【最短路】 (Codeforces Round #372 (Div. 2))

    B. Complete The Graph time limit per test 4 seconds memory limit per test 256 megabytes input standa ...

  3. 【Codeforces】716D Complete The Graph

    D. Complete The Graph time limit per test: 4 seconds memory limit per test: 256 megabytes input: sta ...

  4. CodeForces 715B Complete The Graph 特殊的dijkstra

    Complete The Graph 题解: 比较特殊的dij的题目. dis[x][y] 代表的是用了x条特殊边, y点的距离是多少. 然后我们通过dij更新dis数组. 然后在跑的时候,把特殊边都 ...

  5. Codeforces 715B. Complete The Graph 最短路,Dijkstra,构造

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF715B.html 题解 接下来说的“边”都指代“边权未知的边”. 将所有边都设为 L+1,如果dis(S,T ...

  6. codeforces 715B:Complete The Graph

    Description ZS the Coder has drawn an undirected graph of n vertices numbered from 0 to n - 1 and m ...

  7. 「CF716D」Complete The Graph「最短路」

    题意 给定一个\(n\)个点\(m\)条边的无向图,有一些边权暂时为\(0\),你需要分配一个\([1, 10^{18}]\)的数.最终使得\(s\)到\(t\)最短路为\(L\),输出一个可行的分配 ...

  8. Codeforces Round #372 (Div. 1) B. Complete The Graph (枚举+最短路)

    题目就是给你一个图,图中部分边没有赋权值,要求你把无权的边赋值,使得s->t的最短路为l. 卡了几周的题了,最后还是经群主大大指点……做出来的…… 思路就是跑最短路,然后改权值为最短路和L的差值 ...

  9. Codeforces715 B. Complete The Graph

    传送门:>Here< 题意:给出一张带权无向图,其中有一些边权为0.要求将边权为0的边的边权重置为一个任意的正整数,使得从S到T的最短路为L.判断是否存在这种方案,如果存在输出任意一种 解 ...

随机推荐

  1. 汇编语言笔记v1.0

    1.loop的用法 loop指令的格式是:loop标号,cpu执行loop指令的时候,要进行两步操作 1:(cx)=(cx)-1 2:判断cx中的值,不为零则转至标号处执行,如果为零,则向下执行 这里 ...

  2. python之描述符

    描述符是将某种特殊类型的类实例指派给另一个类的属性,某种特殊类型的类就是这个类里面封装了get,set,delete这三个方法,可以将这个类指派给另一个类的某一个属性,这样就可以通过这三个方法对该属性 ...

  3. docker部署redis及踩到的坑

    对docker很好奇,玩了一下,部署了一个redis,结果踩了很多坑 任务目的就是在docker中成功部署redis并保证数据持久化到本地,配置也使用本地配置 docker run -p : -v $ ...

  4. Ajax数据爬取

    Ajax的基本原理 以菜鸟教程的代码为例: XMLHTTPRequest对象是JS对Ajax的底层实现: var xmlhttp; if (window.XMLHttpRequest) { // IE ...

  5. 你循环的时候就可以给他们赋值了,那么就不用addClass,再根据类选择器处理,代码能一气呵成就别写成两段了

    function onCopyButtonClick() { $(".index:checked").each(function () { $(] + "__WeekCo ...

  6. jmeter发起form-data格式

    两者缺一不可,等下再来研究..

  7. sed 修改文本

    修改文本是指将所匹配的文本行利用新文本替代,sed编辑命令的修改文本符号为 c\, [ sed]$ more input [ sed]$ more aa.sed #!/bin/sed -f //c\ ...

  8. 关于COOKIE在本地可以正常写入发布后不能写入浏览器的问题

    看了一下cookie的属性设置如下: HTTP Cookie       设置了secure ,   该cookie只能在HTTPS通道下被写入浏览器. HTTPS Cookie     设置了sec ...

  9. JIRA API 对接

    系统要跟JIRA对接,将本系统数据发送给jira. 开始一头雾水怎么让数据传过去已什么形式存在,是存数据库呢还是怎么显示呢.研究半天发现其实只要将原数据作为json数据提供给jira接口,jira接口 ...

  10. bzoj 2599

    还是点对之间的问题,果断上点分治 同样,把一条路径拆分成经过根节点的两条路径,对不经过根节点的路径递归处理 然后,我们逐个枚举根节点的子树,计算出子树中某一点到根节点的距离,然后在之前已经处理过的点中 ...