AlexNeagu11

Minimum spanning tree for each edge

Feb 11th, 2022
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.05 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int nax = 200005;
  5.  
  6. struct edge {
  7. int cost, x, y;
  8. };
  9.  
  10. vector<pair<int,int>> adj[nax]; // adj -> minimum spanning treeul
  11. vector<edge> edges; // E -> graful initial
  12. vector<int> p(nax); // p -> vectorul de tati pentru DSU
  13. vector<int> sz(nax, 0); // sz -> marimile colectiilor
  14. vector<int> logaritm(nax * 2);
  15. vector<pair<int,int>> euler; // lista euler - constituita din perechi (nod, nivel)
  16. vector<int> first(nax); // prima aparitie a nodului in lista euler
  17. vector<vector<int>> rmq(nax * 2, vector<int> (20, 0));
  18. vector<int> depth(nax); // nivelul fiecarui nod
  19. vector<vector<int>> big(nax, vector<int> (20, 0)); // small[node][x] -> edgeul cu greutate maxima daca urcam 2^x noduri din node
  20. vector<vector<int>> up(nax, vector<int> (20, 0)); // up[node][x] -> in ce nod ajungem daca urcam cu 2^x noduri din node
  21.  
  22. void dfs(int node, int prdNod, int prdCost, int lvl) {
  23.  
  24. up[node][0] = prdNod;
  25. big[node][0] = prdCost; // urcam cu 2^0 = 1 muchii
  26. for(int i = 1; i < 20; ++i) {
  27. up[node][i] = up[up[node][i - 1]][i - 1];
  28. big[node][i] = max(big[node][i - 1], big[up[node][i - 1]][i - 1]);
  29. }
  30.  
  31. first[node] = euler.size();
  32. euler.push_back({node, lvl});
  33. depth[node] = lvl;
  34. for(auto it : adj[node]) {
  35. if(it.first == prdNod) {
  36. continue;
  37. }
  38. dfs(it.first, node, it.second, lvl + 1);
  39. euler.push_back({node, lvl});
  40. }
  41. }
  42. void computeMins() {
  43. int n = euler.size();
  44. for(int i = 0; i < n; ++i) {
  45. rmq[i][0] = i;
  46. }
  47. for(int i = 1; (1 << i) <= n; ++i) {
  48. for(int j = 0; j + (1 << i) - 1 < n; ++j) {
  49. int k = rmq[j][i - 1];
  50. int l = rmq[j + (1 << (i - 1))][i - 1];
  51. if(euler[k].second < euler[l].second) {
  52. rmq[j][i] = k;
  53. } else {
  54. rmq[j][i] = l;
  55. }
  56. }
  57. }
  58. }
  59. int findLCA(int x, int y) {
  60. x = first[x];
  61. y = first[y];
  62.  
  63. if(x > y) {
  64. swap(x, y);
  65. }
  66. int len = logaritm[y - x + 1];
  67. int k = rmq[x][len];
  68. int l = rmq[y - (1 << len) + 1][len];
  69. if(euler[k].second < euler[l].second) {
  70. return euler[k].first;
  71. }
  72. return euler[l].first;
  73. }
  74.  
  75. bool cmp(edge a, edge b) {
  76. return a.cost < b.cost;
  77. }
  78. int find(int x) {
  79. return (p[x] == x) ? x : p[x] = find(p[x]);
  80. }
  81. void unite(int x, int y) {
  82. if(sz[x] > sz[y]) {
  83. swap(x, y);
  84. }
  85. p[x] = y;
  86. sz[y] += sz[x];
  87. }
  88. int findMax(int x, int y) {
  89. // y deasupra lui x
  90. int mx = 0;
  91. for(int i = 19; i >= 0; --i) {
  92. if(depth[up[x][i]] >= depth[y]) {
  93. mx = max(mx, big[x][i]);
  94. x = up[x][i];
  95. }
  96. }
  97. return mx;
  98. }
  99.  
  100. int32_t main() {
  101. ios_base::sync_with_stdio(false);
  102. cin.tie(0);
  103.  
  104. logaritm[1] = 0;
  105. for(int i = 2; i < 2 * nax; i++) {
  106. logaritm[i] = logaritm[i / 2] + 1;
  107. }
  108.  
  109. int n, m;
  110. cin >> n >> m;
  111.  
  112. vector<edge> initEdges; // copie dupa edges
  113.  
  114. for(int i = 0; i < m; ++i) {
  115. int x, y, c;
  116. cin >> x >> y >> c;
  117. edges.push_back(edge{c, x, y});
  118. initEdges.push_back(edge{c, x, y});
  119. }
  120.  
  121. sort(edges.begin(), edges.end(), cmp);
  122. for(int i = 1; i <= n; ++i) {
  123. p[i] = i; // initializarea DSU-ului
  124. sz[i] = 1;
  125. }
  126.  
  127. int basicCost = 0;
  128.  
  129. for(int i = 0; i < edges.size(); ++i) {
  130. int x = find(edges[i].x), y = find(edges[i].y), cost = edges[i].cost;
  131. if(x == y) {
  132. continue;
  133. }
  134. unite(x, y);
  135. adj[edges[i].x].push_back({edges[i].y, cost});
  136. adj[edges[i].y].push_back({edges[i].x, cost});
  137. basicCost += cost;
  138. }
  139.  
  140. dfs(1, 1, 0, 0);
  141. computeMins();
  142.  
  143. for(int i = 0; i < m; ++i) {
  144.  
  145. int x = initEdges[i].x, y = initEdges[i].y;
  146. int lca = findLCA(x, y);
  147. int deletedEdge = max(findMax(x, lca), findMax(y, lca));
  148. cout << basicCost - deletedEdge + initEdges[i].cost << '\n';
  149.  
  150. }
  151. return 0;
  152. }
  153.  
  154.  
  155.  
  156.  
  157.  
Advertisement
Add Comment
Please, Sign In to add comment