[关闭]
@ljt12138 2019-08-03T21:14:54.000000Z 字数 2073 阅读 506

bzoj3724: PA2014Final Krolestwo

构造 图论


不会欧拉回路怎么办啊【跑

考虑建一个额外的点,所有奇数点连过去跑一个欧拉回路,这样可以构造出一组路径,但不能保证长度为偶数。

考虑进行这样一种操作,将相邻的边缩成对,即将两边的点不经过中点直接相连。如果这样操作可行,显然所有点的奇偶性不变,且在新图上跑欧拉回路可以得到偶数长度的路径。

下面证明这样的操作可行:设表示将子树中所有树边和非树边合并,(如果必须)剩下与其父亲的连边。先对于所有的儿子调用,然后将剩余的边(树边或非树边)两两合并,如果剩下一条,将其和的父亲合并;否则剩下与父亲的边。当这个过程执行到根时,所有的边就合并好了(因为只有可能剩下一条或全部合并成功,而边数为偶数,因此必然全部合并成功)。

于是在新图上跑欧拉回路即可。

写起来像吃了屎一样。。。不过思路很优雅,算法即证明【是不是可以给MO当毒瘤题啊2333

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 500005;
  4. inline int read()
  5. {
  6. int a = 0, c;
  7. do c = getchar(); while (!isdigit(c));
  8. while (isdigit(c)) {
  9. a = a*10+c-'0';
  10. c = getchar();
  11. }
  12. return a;
  13. }
  14. int cnt = 0;
  15. struct node {
  16. int to, next, x, y;
  17. } edge[MAXN*2], e[MAXN*3];
  18. int head[MAXN], top = -1;
  19. int h[MAXN], tot = -1;
  20. inline void push(int i, int j)
  21. { edge[++top] = (node) {j, head[i], 0, 0}, head[i] = top; }
  22. inline void push2(int i, int j, int x, int y)
  23. {
  24. e[++tot] = (node) {j, h[i], x, y}, h[i] = tot;
  25. e[++tot] = (node) {i, h[j], y, x}, h[j] = tot;
  26. }
  27. int vis[MAXN], v[MAXN], d[MAXN], n, m;
  28. void dfs(int nd, int f, int t)
  29. {
  30. int last_to = 0, last_e = 0;
  31. v[nd] = 1;
  32. for (register int i = head[nd]; i != -1; i = edge[i].next) {
  33. int to = edge[i].to;
  34. if (to == f) continue;
  35. if (!v[to]) dfs(to, nd, (i>>1)+1);
  36. if (!vis[(i>>1)+1]) {
  37. if (last_to) push2(last_to, to, last_e, (i>>1)+1), vis[(i>>1)+1] = vis[last_e] = 1, last_to = 0;
  38. else last_to = to, last_e = (i>>1)+1;
  39. }
  40. }
  41. if (last_to) {
  42. push2(last_to, f, last_e, t);
  43. vis[last_e] = vis[t] = 1;
  44. }
  45. }
  46. int ans[MAXN*2], ans_top = 0;
  47. int cur[MAXN];
  48. void dfs_find(int nd)
  49. {
  50. for (int &i = cur[nd]; i != -1; i = e[i].next) {
  51. int to = e[i].to;
  52. if (vis[i>>1]) continue;
  53. vis[i>>1] = 1;
  54. int tmp = i;
  55. dfs_find(to);
  56. if (to == n+1) ans[++ans_top] = -nd;
  57. else if (nd == n+1) ans[++ans_top] = -to;
  58. else ans[++ans_top] = e[tmp].y, ans[++ans_top] = e[tmp].x;
  59. }
  60. }
  61. int main()
  62. {
  63. memset(head, -1, sizeof head);
  64. memset(h, -1, sizeof h);
  65. n = read(), m = read();
  66. for (register int i = 1; i <= m; i++) {
  67. int u = read(), v = read();
  68. d[u]++, d[v]++;
  69. push(u, v), push(v, u);
  70. }
  71. dfs(1, 0, 0);
  72. for (register int i = 1; i <= n; i++)
  73. if (d[i]&1)
  74. push2(i, n+1, -1, -1);
  75. memcpy(cur, h, sizeof h);
  76. memset(vis, 0, sizeof vis);
  77. dfs_find(n+1);
  78. int last = 1, cc = 0;
  79. for (register int i = 2; i <= ans_top; i++) {
  80. if (ans[i] < 0) {
  81. if (last == 0) last = i;
  82. else {
  83. printf("%d %d %d\n", -ans[last], -ans[i], i-last-1), cc += i-last-1;
  84. for (register int j = last+1; j < i; j++)
  85. printf("%d ", ans[j]);
  86. puts("");
  87. last = 0;
  88. }
  89. }
  90. }
  91. return 0;
  92. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注