CF# Educational Codeforces Round 3 E. 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.
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.
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.
5 7
1 2 3
1 3 1
1 4 5
2 3 2
2 5 3
3 4 2
4 5 4
9
8
11
8
8
8
9
题意:给出一个图,问每一条边如果要在一个生成树当中,那这个生成树最小是多少。
分析:先找出一个最小生成树。
想像一下,加入一条边,会对这个生成树造成什么影响。
形成了一个环,然后最优情况,肯定要拿掉除他之外最大的一条边。
问题就变成了,在最小生成树上查询两点之间的边的最大值。
1 /** 2 Create By yzx - stupidboy 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cmath> 8 #include <deque> 9 #include <vector> 10 #include <queue> 11 #include <iostream> 12 #include <algorithm> 13 #include <map> 14 #include <set> 15 #include <ctime> 16 #include <iomanip> 17 using namespace std; 18 typedef long long LL; 19 typedef double DB; 20 #define MIT (2147483647) 21 #define INF (1000000001) 22 #define MLL (1000000000000000001LL) 23 #define sz(x) ((int) (x).size()) 24 #define clr(x, y) memset(x, y, sizeof(x)) 25 #define puf push_front 26 #define pub push_back 27 #define pof pop_front 28 #define pob pop_back 29 #define mk make_pair 30 31 inline int Getint() 32 { 33 int Ret = 0; 34 char Ch = ' '; 35 bool Flag = 0; 36 while(!(Ch >= '0' && Ch <= '9')) 37 { 38 if(Ch == '-') Flag ^= 1; 39 Ch = getchar(); 40 } 41 while(Ch >= '0' && Ch <= '9') 42 { 43 Ret = Ret * 10 + Ch - '0'; 44 Ch = getchar(); 45 } 46 return Flag ? -Ret : Ret; 47 } 48 49 const int N = 200010, M = 20; 50 int n, m; 51 struct EdgeType 52 { 53 int u, v, value, index; 54 LL ans; 55 inline bool operator <(const EdgeType &t) const 56 { 57 return value < t.value; 58 } 59 60 inline void Read() 61 { 62 u = Getint(); 63 v = Getint(); 64 value = Getint(); 65 } 66 } edge[N]; 67 int fa[N], favalue[N]; 68 int first[N], to[N * 2], value[N * 2], next[N * 2], tot; 69 int up[N][M], depth[N], maxcnt[N][M]; 70 LL ans; 71 72 inline void Input() 73 { 74 n = Getint(); 75 m = Getint(); 76 for(int i = 1; i <= m; i++) 77 { 78 edge[i].Read(); 79 edge[i].index = i; 80 } 81 } 82 83 inline int Find(int x) 84 { 85 static int path[N], len; 86 for(len = 0; x != fa[x]; x = fa[x]) 87 path[++len] = x; 88 for(int i = 1; i <= len; i++) fa[path[i]] = x; 89 return x; 90 } 91 92 inline void Insert(int u, int v, int val) 93 { 94 tot++; 95 to[tot] = v, value[tot] = val, next[tot] = first[u]; 96 first[u] = tot; 97 } 98 99 inline void Bfs() 100 { 101 static int que[N], head, tail; 102 for(int i = 1; i <= n; i++) fa[i] = -1; 103 que[1] = 1, head = tail = 1, fa[1] = 0, depth[1] = 1; 104 while(head <= tail) 105 { 106 int u = que[head++]; 107 for(int tab = first[u], v; tab; tab = next[tab]) 108 if(fa[v = to[tab]] == -1) 109 { 110 fa[v] = u, favalue[v] = value[tab], depth[v] = depth[u] + 1; 111 que[++tail] = v; 112 } 113 } 114 } 115 116 inline int GetMax(int u, int v) 117 { 118 int ret = 0, level = M; 119 while(depth[u] != depth[v]) 120 { 121 if(depth[u] < depth[v]) swap(u, v); 122 while(level && (1 << level) > depth[u] - depth[v]) level--; 123 ret = max(ret, maxcnt[u][level]); 124 u = up[u][level]; 125 } 126 level = M; 127 while(level && u != v) 128 { 129 while(level && (1 << level) > depth[u]) level--; 130 while(level && up[u][level] == up[v][level]) level--; 131 ret = max(ret, maxcnt[u][level]); 132 ret = max(ret, maxcnt[v][level]); 133 u = up[u][level], v = up[v][level]; 134 } 135 while(u != v) 136 { 137 ret = max(ret, favalue[u]); 138 ret = max(ret, favalue[v]); 139 u = fa[u], v = fa[v]; 140 } 141 return ret; 142 } 143 144 inline bool CompareByIndex(const EdgeType &a, const EdgeType &b) 145 { 146 return a.index < b.index; 147 } 148 149 inline void Solve() 150 { 151 sort(edge + 1, edge + 1 + m); 152 for(int i = 1; i <= n; i++) fa[i] = i; 153 for(int i = 1; i <= m; i++) 154 { 155 int u = Find(edge[i].u), v = Find(edge[i].v); 156 if(u != v) 157 { 158 Insert(edge[i].u, edge[i].v, edge[i].value); 159 Insert(edge[i].v, edge[i].u, edge[i].value); 160 ans += edge[i].value; 161 fa[u] = v; 162 } 163 } 164 165 Bfs(); 166 167 for(int i = 0; i < M; i++) 168 { 169 if((1 << i) > n) break; 170 for(int j = 1; j <= n; j++) 171 if(i == 0) 172 { 173 up[j][i] = fa[j]; 174 maxcnt[j][i] = favalue[j]; 175 } 176 else 177 { 178 up[j][i] = up[up[j][i - 1]][i - 1]; 179 maxcnt[j][i] = max(maxcnt[j][i - 1], maxcnt[up[j][i - 1]][i - 1]); 180 } 181 } 182 183 184 for(int i = 1; i <= m; i++) 185 { 186 int u = edge[i].u, v = edge[i].v; 187 int ret = GetMax(u, v); 188 edge[i].ans = ans - ret + edge[i].value; 189 } 190 191 sort(edge + 1, edge + 1 + m, CompareByIndex); 192 for(int i = 1; i <= m; i++) printf("%I64d\n", edge[i].ans); 193 } 194 195 int main() 196 { 197 freopen("a.in", "r", stdin); 198 Input(); 199 Solve(); 200 return 0; 201 }