[关闭]
@ZCDHJ 2019-08-14T06:50:06.000000Z 字数 3494 阅读 593

FJOI2014 最短路径树问题

未分类


将最短路树建出来,点分治就行了。

因为最大值不能直接容斥,所以每次分别计算子树的贡献。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <queue>
  5. #include <cstring>
  6. const int MAXN = 3e4;
  7. const int MAXM = 6e4;
  8. int n, m, K, edge1, edge2, allSize, root, ans1, ans2;
  9. int fst1[MAXN | 1], fst2[MAXN | 1];
  10. int f[MAXN | 1], size[MAXN | 1];
  11. int maxx[MAXN | 1], sumx[MAXN | 1];
  12. bool vis[MAXN | 1];
  13. struct E {
  14. int u, v, w;
  15. E() : u(0), v(0), w(0) {}
  16. E(int x, int y, int z) : u(x), v(y), w(z) {}
  17. } a[MAXM | 1];
  18. inline bool comp1(const E &lhs, const E &rhs) {
  19. return lhs.v > rhs.v;
  20. }
  21. inline bool comp2(const E &lhs, const E &rhs) {
  22. return lhs.u > rhs.u;
  23. }
  24. struct Edge {
  25. int to, w, nxt;
  26. Edge() : to(0), w(0), nxt(0) {}
  27. Edge(int a, int b, int c) : to(b), w(c), nxt(a) {}
  28. } e1[MAXM << 1 | 1], e2[MAXM << 1 | 1];
  29. struct Heap {
  30. int x, dis;
  31. Heap() : x(0), dis(0) {}
  32. Heap(int a, int b) : x(a), dis(b) {}
  33. friend bool operator< (const Heap &lhs, const Heap &rhs) {
  34. return lhs.dis > rhs.dis;
  35. }
  36. };
  37. inline int read() {
  38. register int x = 0;
  39. register char ch = getchar();
  40. while (!isdigit(ch)) ch = getchar();
  41. while (isdigit(ch)) {
  42. x = x * 10 + ch - '0';
  43. ch = getchar();
  44. }
  45. return x;
  46. }
  47. void Dijkstra() {
  48. std::priority_queue < Heap > q;
  49. int dist[MAXN | 1];
  50. memset(dist, 0x3f, sizeof(dist));
  51. dist[1] = 0;
  52. q.push(Heap(1, 0));
  53. do {
  54. Heap from = q.top();
  55. q.pop();
  56. if (from.dis != dist[from.x]) continue;
  57. for (int k = fst1[from.x]; k; k = e1[k].nxt) {
  58. int to = e1[k].to, w = e1[k].w;
  59. if (dist[to] > dist[from.x] + w) {
  60. dist[to] = dist[from.x] + w;
  61. q.push(Heap(to, dist[to]));
  62. }
  63. }
  64. } while (!q.empty());
  65. std::queue < int > qq;
  66. qq.push(1);
  67. do {
  68. int from = qq.front();
  69. qq.pop();
  70. for (int k = fst1[from]; k; k = e1[k].nxt) {
  71. int to = e1[k].to, w = e1[k].w;
  72. if (dist[to] == dist[from] + w && !vis[to]) {
  73. vis[to] = 1;
  74. e2[++edge2] = Edge(fst2[from], to, w);
  75. fst2[from] = edge2;
  76. e2[++edge2] = Edge(fst2[to], from, w);
  77. fst2[to] = edge2;
  78. qq.push(to);
  79. }
  80. }
  81. } while (!qq.empty());
  82. }
  83. void getRoot(int x, int fa) {
  84. size[x] = 1;
  85. f[x] = 0;
  86. for (int k = fst2[x]; k; k = e2[k].nxt) {
  87. int to = e2[k].to;
  88. if (to == fa || vis[to]) continue;
  89. getRoot(to, x);
  90. size[x] += size[to];
  91. f[x] = std::max(f[x], size[to]);
  92. }
  93. f[x] = std::max(f[x], allSize - size[x]);
  94. if (f[x] < f[root] || root == 0) root = x;
  95. }
  96. void getSonAns(int x, int fa, int ww, int depth) {
  97. if (depth >= K) return;
  98. if (maxx[K - 1 - depth] + ww > ans1) {
  99. ans1 = maxx[K - 1 - depth] + ww;
  100. ans2 = sumx[K - 1 - depth];
  101. } else if (maxx[K - 1 - depth] + ww == ans1) ans2 += sumx[K - 1 - depth];
  102. for (int k = fst2[x]; k; k = e2[k].nxt) {
  103. int to = e2[k].to, w = e2[k].w;
  104. if (to == fa || vis[to]) continue;
  105. getSonAns(to, x, ww + w, depth + 1);
  106. }
  107. }
  108. void getDis(int x, int fa, int ww, int depth) {
  109. if (depth >= K) return;
  110. if (ww > maxx[depth]) {
  111. maxx[depth] = ww;
  112. sumx[depth] = 1;
  113. } else if (ww == maxx[depth]) ++sumx[depth];
  114. for (int k = fst2[x]; k; k = e2[k].nxt) {
  115. int to = e2[k].to, w = e2[k].w;
  116. if (to == fa || vis[to]) continue;
  117. getDis(to, x, ww + w, depth + 1);
  118. }
  119. }
  120. void remove(int x, int fa, int ww, int depth) {
  121. if (depth >= K) return;
  122. maxx[depth] = 0;
  123. sumx[depth] = 0;
  124. for (int k = fst2[x]; k; k = e2[k].nxt) {
  125. int to = e2[k].to, w = e2[k].w;
  126. if (to == fa || vis[to]) continue;
  127. remove(to, x, ww + w, depth + 1);
  128. }
  129. }
  130. void getAns(int x) {
  131. maxx[0] = 0;
  132. sumx[0] = 1;
  133. for (int k = fst2[x]; k; k = e2[k].nxt) {
  134. int to = e2[k].to, w = e2[k].w;
  135. if (!vis[to]) {
  136. getSonAns(to, x, w, 1);
  137. getDis(to, x, w, 1);
  138. }
  139. }
  140. for (int k = fst2[x]; k; k = e2[k].nxt) {
  141. int to = e2[k].to, w = e2[k].w;
  142. if (!vis[to]) remove(to, x, w, 1);
  143. }
  144. }
  145. void DAC(int x) {
  146. vis[x] = 1;
  147. getAns(x);
  148. // printf("ffffrom=%d ans1=%d ans2=%d\n", x, ans1, ans2);
  149. int lstSize = allSize;
  150. for (int k = fst2[x]; k; k = e2[k].nxt) {
  151. int to = e2[k].to;
  152. if (vis[to]) continue;
  153. allSize = size[to] > size[x] ? lstSize - size[x] : size[to];
  154. root = 0;
  155. getRoot(to, x);
  156. DAC(root);
  157. }
  158. }
  159. int main() {
  160. n = read();
  161. m = read();
  162. K = read();
  163. for (int i = 1; i <= m; ++i) {
  164. a[i].u = read();
  165. a[i].v = read();
  166. a[i].w = read();
  167. }
  168. std::sort(a + 1, a + m + 1, comp1);
  169. for (int i = 1; i <= m; ++i) {
  170. e1[++edge1] = Edge(fst1[a[i].u], a[i].v, a[i].w);
  171. fst1[a[i].u] = edge1;
  172. }
  173. std::sort(a + 1, a + m + 1, comp2);
  174. for (int i = 1; i <= m; ++i) {
  175. e1[++edge1] = Edge(fst1[a[i].v], a[i].u, a[i].w);
  176. fst1[a[i].v] = edge1;
  177. }
  178. Dijkstra();
  179. allSize = n;
  180. memset(vis, 0, sizeof(vis));
  181. getRoot(1, 0);
  182. DAC(root);
  183. printf("%d %d\n", ans1, ans2);
  184. return 0;
  185. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注