1
0

CodeForces-609E.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <numeric>
  4. #include <queue>
  5. #include <tuple>
  6. #include <vector>
  7. using namespace std;
  8. struct DSU {
  9. vector<int> p, s;
  10. explicit DSU(int n) : p(n), s(n, 1) { iota(p.begin(), p.end(), 0); }
  11. int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
  12. bool unite(int a, int b) {
  13. a = find(a); b = find(b); if (a == b) return false;
  14. if (s[a] < s[b]) swap(a, b); p[b] = a; s[a] += s[b]; return true;
  15. }
  16. };
  17. struct Edge { int u, v; long long w; bool tree = false; };
  18. int main() {
  19. ios::sync_with_stdio(false);
  20. cin.tie(nullptr);
  21. int n, m; cin >> n >> m;
  22. vector<Edge> edges(m); vector<int> order(m);
  23. for (int i = 0; i < m; ++i) {
  24. cin >> edges[i].u >> edges[i].v >> edges[i].w;
  25. --edges[i].u; --edges[i].v; order[i] = i;
  26. }
  27. sort(order.begin(), order.end(), [&](int a, int b) { return edges[a].w < edges[b].w; });
  28. vector<vector<pair<int, long long>>> tree(n);
  29. DSU dsu(n); long long total = 0;
  30. for (int id : order) if (dsu.unite(edges[id].u, edges[id].v)) {
  31. edges[id].tree = true; total += edges[id].w;
  32. tree[edges[id].u].push_back({edges[id].v, edges[id].w});
  33. tree[edges[id].v].push_back({edges[id].u, edges[id].w});
  34. }
  35. constexpr int log = 20;
  36. vector<vector<int>> up(log, vector<int>(n));
  37. vector<vector<long long>> maximum(log, vector<long long>(n));
  38. vector<int> depth(n, -1); queue<int> q; depth[0] = 0; up[0][0] = 0; q.push(0);
  39. while (!q.empty()) {
  40. int u = q.front(); q.pop();
  41. for (auto [v, w] : tree[u]) if (depth[v] == -1) {
  42. depth[v] = depth[u] + 1; up[0][v] = u; maximum[0][v] = w; q.push(v);
  43. }
  44. }
  45. for (int j = 1; j < log; ++j) for (int v = 0; v < n; ++v) {
  46. up[j][v] = up[j - 1][up[j - 1][v]];
  47. maximum[j][v] = max(maximum[j - 1][v], maximum[j - 1][up[j - 1][v]]);
  48. }
  49. auto path_max = [&](int u, int v) {
  50. long long answer = 0;
  51. if (depth[u] < depth[v]) swap(u, v);
  52. for (int j = log - 1; j >= 0; --j) if (depth[u] - (1 << j) >= depth[v]) {
  53. answer = max(answer, maximum[j][u]); u = up[j][u];
  54. }
  55. if (u == v) return answer;
  56. for (int j = log - 1; j >= 0; --j) if (up[j][u] != up[j][v]) {
  57. answer = max({answer, maximum[j][u], maximum[j][v]});
  58. u = up[j][u]; v = up[j][v];
  59. }
  60. return max({answer, maximum[0][u], maximum[0][v]});
  61. };
  62. for (const Edge &e : edges) {
  63. cout << (e.tree ? total : total + e.w - path_max(e.u, e.v)) << '\n';
  64. }
  65. }