codeforces 609E. Minimum spanning tree for each edge 树链剖分
给一个n个节点m条边的树, 每条边有权值, 输出m个数, 每个数代表包含这条边的最小生成树的值。
先将最小生成树求出来, 把树边都标记。 然后对标记的边的两个端点, 我们add(u, v), add(v, u)。 对于每一次输出, 如果这条边被标记了, 那么直接输出mst的值。 否则, 加上这条边之后一定会出现一个环, 我们就把环上的最长的那条边删掉。 查询最长的那条边可以用树链剖分。
1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <cmath> 7 #include <map> 8 #include <set> 9 #include <string> 10 #include <queue> 11 #include <stack> 12 #include <bitset> 13 using namespace std; 14 #define pb(x) push_back(x) 15 #define ll long long 16 #define mk(x, y) make_pair(x, y) 17 #define lson l, m, rt<<1 18 #define mem(a) memset(a, 0, sizeof(a)) 19 #define rson m+1, r, rt<<1|1 20 #define mem1(a) memset(a, -1, sizeof(a)) 21 #define mem2(a) memset(a, 0x3f, sizeof(a)) 22 #define rep(i, n, a) for(int i = a; i<n; i++) 23 #define fi first 24 #define se second 25 typedef pair<int, int> pll; 26 const double PI = acos(-1.0); 27 const double eps = 1e-8; 28 const int mod = 1e9+7; 29 const int inf = 1061109567; 30 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 31 const int maxn = 2e5+5; 32 int head[maxn*2], son[maxn], sz[maxn], deep[maxn], top[maxn], w[maxn], f[maxn], cnt, num; 33 int maxx[maxn<<2], fa[maxn]; 34 struct node 35 { 36 int to, nextt; 37 }e[maxn*2]; 38 struct ed 39 { 40 int u, v, id, val, mark; 41 ed(){} 42 ed(int u, int v, int val, int id, int mark = 0):u(u), v(v), val(val), id(id), mark(mark){} 43 }edge[maxn]; 44 bool cmp1(ed a, ed b) { 45 return a.id<b.id; 46 } 47 bool cmp2(ed a, ed b) { 48 if(a.val == b.val) 49 return a.id<b.id; 50 return a.val<b.val; 51 } 52 void init() { 53 mem1(head); 54 num = cnt = 0; 55 } 56 void add(int u, int v, int w) { 57 e[num].to = v, e[num].nextt = head[u], head[u] = num++; 58 } 59 void dfs1(int u, int fa) { 60 sz[u] = 1; 61 deep[u] = deep[fa]+1; 62 son[u] = -1; 63 f[u] = fa; 64 for(int i = head[u]; ~i; i = e[i].nextt) { 65 int v = e[i].to; 66 if(v == fa) 67 continue; 68 dfs1(v, u); 69 sz[u] += sz[v]; 70 if(son[u]==-1||sz[v]>sz[son[u]]) 71 son[u] = v; 72 } 73 } 74 void dfs2(int u, int tp) { 75 w[u] = ++cnt, top[u] = tp; 76 if(~son[u]) 77 dfs2(son[u], tp); 78 for(int i = head[u]; ~i; i = e[i].nextt) { 79 int v = e[i].to; 80 if(v == f[u]||v == son[u]) 81 continue; 82 dfs2(v, v); 83 } 84 } 85 void pushUp(int rt) { 86 maxx[rt] = max(maxx[rt<<1], maxx[rt<<1|1]); 87 } 88 void update(int p, int val, int l, int r, int rt) { 89 if(l == r) { 90 maxx[rt] = val; 91 return ; 92 } 93 int m = l+r>>1; 94 if(p<=m) 95 update(p, val, lson); 96 else 97 update(p, val, rson); 98 pushUp(rt); 99 } 100 int query(int L, int R, int l, int r, int rt) { 101 if(L<=l&&R>=r) { 102 return maxx[rt]; 103 } 104 int m = l+r>>1, ret = 0; 105 if(L<=m) 106 ret = max(ret, query(L, R, lson)); 107 if(R>m) 108 ret = max(ret, query(L, R, rson)); 109 return ret; 110 } 111 int find(int u, int v) { 112 int f1 = top[u], f2 = top[v], ret = 0; 113 while(f1 != f2) { 114 if(deep[f1]<deep[f2]) { 115 swap(f1, f2); 116 swap(u, v); 117 } 118 ret = max(ret, query(w[f1], w[u], 1, cnt, 1)); 119 u = f[f1]; 120 f1 = top[u]; 121 } 122 if(u == v) 123 return ret; 124 if(deep[u]>deep[v]) 125 swap(u, v); 126 return max(ret, query(w[son[u]], w[v], 1, cnt, 1)); 127 } 128 int findd(int u) { 129 return fa[u] == u?u:fa[u] = findd(fa[u]); 130 } 131 int main() 132 { 133 int t, n, u, v, val, m; 134 while(~scanf("%d%d", &n, &m)) { 135 init(); 136 ll mst = 0; 137 deep[0] = 0; 138 for(int i = 1; i<=m; i++) { 139 scanf("%d%d%d", &u, &v, &val); 140 edge[i] = ed(u, v, val, i); 141 } 142 for(int i = 1; i<=n; i++) 143 fa[i] = i; 144 sort(edge+1, edge+1+m, cmp2); 145 for(int i = 1; i<=m; i++) { 146 u = findd(edge[i].u); 147 v = findd(edge[i].v); 148 if(u == v) 149 continue; 150 edge[i].mark = 1; 151 fa[v] = u; 152 mst += edge[i].val; 153 } 154 for(int i = 1; i<=m; i++) { 155 if(edge[i].mark) { 156 add(edge[i].u, edge[i].v, edge[i].val); 157 add(edge[i].v, edge[i].u, edge[i].val); 158 } 159 } 160 dfs1(1, 0); 161 dfs2(1, 1); 162 for(int i = 1; i<=m; i++) { 163 if(deep[edge[i].u]>deep[edge[i].v]) { 164 swap(edge[i].u, edge[i].v); 165 } 166 if(edge[i].mark) 167 update(w[edge[i].v], edge[i].val, 1, cnt, 1); 168 } 169 sort(edge+1, edge+1+m, cmp1); 170 for(int i = 1; i<=m; i++) { 171 if(edge[i].mark) { 172 printf("%I64d\n", mst); 173 } else { 174 int tmp = find(edge[i].u, edge[i].v); 175 printf("%I64d\n", mst-tmp+edge[i].val); 176 } 177 } 178 } 179 return 0; 180 }