CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge

E. Minimum spanning tree for each edge
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Sample test(s)
input
5 7
1 2 3
1 3 1
1 4 5
2 3 2
2 5 3
3 4 2
4 5 4
output
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 }
View Code

 

posted @ 2015-12-22 22:05  yanzx6  阅读(291)  评论(0编辑  收藏  举报