2001: [Hnoi2010]City 城市建设
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1132 Solved: 555
[Submit][Status][Discuss]
Description
PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁。Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费。Louis希望建造最少的道路使得国内所有的城市连通。但是由于某些因素,城市之间修建道路需要的花费会随着时间而改变,Louis会不断得到某道路的修建代价改变的消息,他希望每得到一条消息后能立即知道使城市连通的最小花费总和, Louis决定求助于你来完成这个任务。
Input
文件第一行包含三个整数N,M,Q,分别表示城市的数目,可以修建的道路个数,及收到的消息个数。 接下来M行,第i+1行有三个用空格隔开的整数Xi,Yi,Zi(1≤Xi,Yi≤n, 0≤Zi≤50000000),表示在城市Xi与城市Yi之间修建道路的代价为Zi。接下来Q行,每行包含两个数k,d,表示输入的第k个道路的修建代价修改为d(即将Zk修改为d)。
Output
输出包含Q行,第i行输出得知前i条消息后使城市连通的最小花费总和。
Sample Input
1 2 1
2 3 2
3 4 3
4 5 4
5 1 5
1 6
1 1
5 3
Sample Output
10
9
HINT
【数据规模】 对于20%的数据, n≤1000,m≤6000,Q≤6000。 有20%的数据,n≤1000,m≤50000,Q≤8000,修改后的代价不会比之前的代价低。 对于100%的数据, n≤20000,m≤50000,Q≤50000。
Source
十分懵逼的一道CDQ分治。
solve(l,r) 解决l到r区间内的修改及询问。
边界:l==r,可以直接做最小生成树得到答案。
其他:递归之前,需要在当前层进行两个操作:
contraction 求出所有的必须边,并直接把必须边加入答案,之后不再考虑;顺道把必须边连接的两点永久合并。
reduction 求出所有的不可能边,并直接把不可能边删除,之后不再考虑。
把所有待修改的边权值设为-inf,做最小生成树,在MST上的非待修改边都是必须边。
把所有待修改的边权值设为+inf,做最小生成树,不在MST上的非待修改边都是不可能边。
进行两个操作之后,图的规模会缩小,也许是缩小一半,不造,这个太玄学,大爷都不会。
1 #include <bits/stdc++.h> 2 3 inline int getC(void) { 4 static const int siz = 1024; 5 6 static char buf[siz]; 7 static char *hd = buf + siz; 8 static char *tl = buf + siz; 9 10 if (hd == tl) 11 fread(hd = buf, 1, siz, stdin); 12 13 return int(*hd++); 14 } 15 16 inline int getI(void) { 17 register int ret = 0; 18 register int neg = false; 19 register int bit = getC(); 20 21 for (; bit < 48; bit = getC()) 22 if (bit == '-')neg ^= true; 23 24 for (; bit > 47; bit = getC()) 25 ret = ret * 10 + bit - '0'; 26 27 return neg ? -ret : ret; 28 } 29 30 typedef long long lnt; 31 32 const int inf = 1e9; 33 const int maxn = 20005; 34 const int maxm = 50005; 35 36 int N, M, Q; 37 38 int a[maxm]; 39 int c[maxm]; 40 41 int sum[maxn]; 42 43 lnt ans[maxm]; 44 45 struct edge { 46 int x, y, w, p; 47 48 inline friend bool operator < 49 (const edge &a, const edge &b) { 50 return a.w < b.w; 51 } 52 }e[25][maxm], d[maxm], b[maxm]; 53 54 struct edit { 55 int x, y; 56 }q[maxm]; 57 58 int fa[maxn]; 59 60 int find(int u) { 61 return fa[u] == u ? u : fa[u] = find(fa[u]); 62 } 63 64 inline void clear(int t) { 65 for (int i = 1; i <= t; ++i) 66 fa[d[i].x] = d[i].x, 67 fa[d[i].y] = d[i].y; 68 } 69 70 inline void merge(int x, int y) { 71 fa[y] = x; 72 } 73 74 inline void contraction(int &t, lnt &cnt) { 75 clear(t); int tmp = 0; 76 std::sort(d + 1, d + 1 + t); 77 78 for (int i = 1; i <= t; ++i) 79 if (find(d[i].x) != find(d[i].y)) 80 merge(find(d[i].x), find(d[i].y)), b[++tmp] = d[i]; 81 82 for (int i = 1; i <= tmp; ++i) 83 fa[b[i].x] = b[i].x, 84 fa[b[i].y] = b[i].y; 85 86 for (int i = 1; i <= tmp; ++i) 87 if (b[i].w != -inf && find(b[i].x) != find(b[i].y)) 88 merge(find(b[i].x), find(b[i].y)), cnt += b[i].w; 89 90 tmp = 0; 91 92 for (int i = 1; i <= t; ++i) 93 if (find(d[i].x) != find(d[i].y)) { 94 b[++tmp] = d[i]; 95 c[d[i].p] = tmp; 96 b[tmp].x = find(d[i].x); 97 b[tmp].y = find(d[i].y); 98 } 99 100 for (int i = 1; i <= tmp; ++i)d[i] = b[i]; 101 102 t = tmp; 103 } 104 105 inline void reduction(int &t) { 106 clear(t); int tmp = 0; 107 std::sort(d + 1, d + 1 + t); 108 109 for (int i = 1; i <= t; ++i) 110 if (find(d[i].x) != find(d[i].y)) { 111 merge(find(d[i].x), find(d[i].y)); 112 b[++tmp] = d[i]; 113 c[d[i].p] = tmp; 114 } 115 else if (d[i].w == inf) { 116 b[++tmp] = d[i]; 117 c[d[i].p] = tmp; 118 } 119 120 for (int i = 1; i <= tmp; ++i)d[i] = b[i]; 121 122 t = tmp; 123 } 124 125 void solve(int l, int r, int now, lnt cnt) { 126 int t = sum[now]; 127 128 if (l == r)a[q[l].x] = q[l].y; 129 130 for (int i = 1; i <= t; ++i) 131 e[now][i].w = a[e[now][i].p]; 132 133 for (int i = 1; i <= t; ++i) 134 d[i] = e[now][i], c[d[i].p] = i; 135 136 if (l == r) { 137 ans[l] = cnt; clear(t); 138 std::sort(d + 1, d + 1 + t); 139 for (int i = 1; i <= t; ++i) 140 if (find(d[i].x) != find(d[i].y)) 141 merge(find(d[i].x), find(d[i].y)), ans[l] += d[i].w; 142 return; 143 } 144 145 for (int i = l; i <= r; ++i) 146 d[c[q[i].x]].w = -inf; 147 148 contraction(t, cnt); 149 150 for (int i = l; i <= r; ++i) 151 d[c[q[i].x]].w = inf; 152 153 reduction(t); 154 155 for (int i = 1; i <= t; ++i) 156 e[now + 1][i] = d[i]; 157 158 sum[now + 1] = t; 159 160 int mid = (l + r) >> 1; 161 162 solve(l, mid, now + 1, cnt); 163 solve(mid + 1, r, now + 1, cnt); 164 } 165 166 signed main(void) { 167 N = getI(); 168 M = getI(); 169 Q = getI(); 170 171 for (int i = 1; i <= M; ++i) { 172 e[0][i].p = i; 173 e[0][i].x = getI(); 174 e[0][i].y = getI(); 175 e[0][i].w = getI(); 176 a[i] = e[0][i].w; 177 } 178 179 for (int i = 1; i <= Q; ++i) { 180 q[i].x = getI(); 181 q[i].y = getI(); 182 } 183 184 sum[0] = M; 185 186 solve(1, Q, 0, 0); 187 188 for (int i = 1; i <= Q; ++i) 189 printf("%lld ", ans[i]); 190 }
@Author: YouSiki