Minimum spanning tree for each edge

Connected undirected weighted graph without self-loops and multiple edges is given. Graph contains n vertices and m edges.

For each edge (u,?v) find the minimal possible weight of the spanning tree that contains the edge (u,?v).

The weight of the spanning tree is the sum of weights of all edges included in spanning tree.

Input

First line contains two integers n and m (1?≤?n?≤?2·105,?n?-?1?≤?m?≤?2·105) — the number of vertices and edges in graph.

Each of the next m lines contains three integers ui,?vi,?wi (1?≤?ui,?vi?≤?n,?ui?≠?vi,?1?≤?wi?≤?109) — the endpoints of the i-th edge and its weight.

Output

Print m lines. i-th line should contain the minimal possible weight of the spanning tree that contains i-th edge.

The edges are numbered from 1 to m in order of their appearing in input.

Examples

Input

Copy

5 71 2 31 3 11 4 52 3 22 5 33 4 24 5 4

Output

98118889题解:建最小支撑树,往里面加边u-v,那么容易想到的是ans=minTree-max{u-....-v这条链上的最大值}+va[u-v]。这里和LCA联系上了,记录从两端点向上跳2^k次得到的最大值,直到跳到u和v的公共祖先。
  1 #pragma warning(disable:4996)
  2 #include<bitset>
  3 #include<string>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<algorithm>
  8 using namespace std;
  9 typedef long long ll;
 10
 11 const int INF = 2e9 + 9;
 12 const int maxn = 200005;
 13
 14 int n, m, tot, root;
 15 int head[maxn], pa[maxn][20], dp[maxn], Fa[maxn], as[maxn][20];
 16
 17 struct node { int u, v, w; } a[maxn], b[maxn];
 18 struct mode { int to, va, next; } e[2*maxn];
 19
 20 bool cmp(node& x, node& y) { return x.w < y.w; }
 21
 22 void Inite() {
 23     tot = 0;
 24     memset(head, -1, sizeof(head));
 25
 26     memset(as, 0, sizeof(as));
 27     memset(dp, 0, sizeof(dp));
 28     memset(pa, -1, sizeof(pa));
 29     for (int i = 1; i <= n; i++) Fa[i] = i;
 30 }
 31
 32 void addedge(int u, int v, int w) {
 33     e[tot].to = v;
 34     e[tot].va = w;
 35     e[tot].next = head[u];
 36     head[u] = tot++;
 37 }
 38
 39 int Find(int a) {
 40     if (a == Fa[a]) return a;
 41     return Fa[a] = Find(Fa[a]);
 42 }
 43
 44 bool Union(int a, int b) {
 45     int x = Find(a), y = Find(b);
 46     if (x == y) return false;
 47     else {
 48         Fa[x] = y;
 49         return true;
 50     }
 51 }
 52
 53 ll minTree() {
 54     sort(a + 1, a + m + 1, cmp);
 55     ll ans = 0;
 56     for (int i = 1; i <= m; i++) {
 57         if (Union(a[i].u, a[i].v)) {
 58             ans += a[i].w;
 59             root = a[i].u;
 60             addedge(a[i].u, a[i].v, a[i].w);
 61             addedge(a[i].v, a[i].u, a[i].w);
 62         }
 63     }
 64     return ans;
 65 }
 66
 67 void DFS(int u, int p, int deep) {
 68     pa[u][0] = p;
 69     dp[u] = deep;
 70     for (int i = head[u]; i != -1; i = e[i].next) {
 71         int v = e[i].to;
 72         if (v == p) continue;
 73         as[v][0] = e[i].va;
 74         DFS(v, u, deep + 1);
 75     }
 76 }
 77
 78 void getPa() {
 79     DFS(root, -1, 0);
 80     for (int i = 1; (1 << i) < n; i++) {
 81         for (int j = 1; j <= n; j++) {
 82             if (pa[j][i - 1] != -1) {
 83                 pa[j][i] = pa[pa[j][i - 1]][i - 1];
 84                 as[j][i] = max(as[j][i - 1], as[pa[j][i - 1]][i - 1]);
 85             }
 86         }
 87     }
 88 }
 89
 90 int Lca(int u, int v) {
 91     if (dp[u] > dp[v]) swap(u, v);
 92     int ans = 0;
 93     for (int i = 0; i <= 19; i++) if ((dp[v] - dp[u]) >> i & 1) { ans = max(ans, as[v][i]); v = pa[v][i]; }
 94     if (u == v) return ans;
 95     for (int i = 19; i >= 0; i--) {
 96         if (pa[u][i] != pa[v][i]) {
 97             int tmp = max(as[u][i], as[v][i]);
 98             ans = max(ans, tmp);
 99             u = pa[u][i];
100             v = pa[v][i];
101         }
102     }
103     int tmp = max(as[u][0], as[v][0]);
104     ans = max(ans, tmp);
105     return ans;
106 }
107
108 int main()
109 {
110     while (scanf("%d%d", &n, &m) != EOF) {
111         Inite();
112         for (int i = 1; i <= m; i++) scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);
113         for (int i = 1; i <= m; i++) b[i].u = a[i].u, b[i].v = a[i].v, b[i].w = a[i].w;
114
115         ll ans1 = minTree();
116         //cout << "root" << " " << root << endl;
117
118         getPa();
119         for (int i = 1; i <= m; i++) {
120             int ans2 = Lca(b[i].u, b[i].v);
121             printf("%I64d\n", ans1 + b[i].w - ans2);
122         }
123     }
124     return 0;
125 }

原文地址:https://www.cnblogs.com/zgglj-com/p/8735347.html

时间: 2024-08-30 01:49:42

Minimum spanning tree for each edge的相关文章

CF609E. Minimum spanning tree for each edge

题解:随便构造一颗最小生成树 然后对于其他不在树上的边  考虑到 删除这条链上的最大值在把这条边加上去 能得到这条边所在的最小生成树 可以LCT维护 但是明显这个题是静态的树就没必要LCT 当然我觉得最优的是树剖以后ST nlogn的的复杂度 也可以树剖+线段树nlog^2的复杂度 #include <bits/stdc++.h> const int MAXN=2e5+10; #define ll long long using namespace std; ll read(){ ll x=0

Educational Codeforces Round 3 E (609E) Minimum spanning tree for each edge

题意:一个无向图联通中,求包含每条边的最小生成树的值(无自环,无重边) 分析:求出这个图的最小生成树,用最小生成树上的边建图 对于每条边,不外乎两种情况 1:该边就是最小生成树上的边,那么答案显然 2:该边不在最小生成树上,那么进行路径查询,假设加入这条边,那么形成一个环,删去这个环上除该边外的最大权值边,形成一棵树 树的权值即为答案.(并不需要真正加入这条边) 注:其实用树链剖分和LCA都可以,选择自己熟悉的写就行,我写的树链剖分 #include<cstdio> #include<c

cf 609E.Minimum spanning tree for each edge

最小生成树,lca(树链剖分(太难搞,不会写)) 问存在这条边的最小生成树,2种情况.1.这条边在原始最小生成树上.2.加上这条半形成一个环(加上),那么就找原来这条边2端点间的最大边就好(减去).(sum+val-max) (代码冗长) 1 #include<bits/stdc++.h> 2 #define LL long long 3 #define N 100005 4 using namespace std; 5 inline int ra() 6 { 7 int x=0,f=1; c

【HDU 4408】Minimum Spanning Tree(最小生成树计数)

Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX finds that there might be multiple solutions. Given an undirected weighted graph with n (1<=n<=100) vertex

HDOJ 题目4408 Minimum Spanning Tree(Kruskal+Matrix_Tree)

Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1408    Accepted Submission(s): 450 Problem Description XXX is very interested in algorithm. After learning the Prim algori

Geeks : Kruskal’s Minimum Spanning Tree Algorithm 最小生成树

寻找图中最小连通的路径,图如下: 算法步骤: 1. Sort all the edges in non-decreasing order of their weight. 2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge. Else, discard it. 3. Repeat st

HDU 4408 Minimum Spanning Tree 最小生成树计数

Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem Description] XXX is very interested in algorithm. After learning the Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX

[思维]Minimum Spanning Tree

题目描述 In the mathematical discipline of graph theory, the line graph of a simple undirected weighted graph G is another simple undirected weighted graph L(G) that represents the adjacency between every two edges in G. Precisely speaking, for an undire

【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情况下,我们把图看成是一种由"顶点"和"边"组成的抽象网络.在各个"顶点"间可以由"边"连接起来,使两个顶点间相互关联起来.图的结构可以描述多种复杂的数据对象,