#include<cstdio> #include<vector> #include<algorithm> enum { MAX = 200010*2, }; int vol[MAX]; std::vector<int> tree[MAX]; int find_and_union[MAX]; bool gotit[MAX]; int LCA[20][MAX*2]; int LCA_id[MAX]; int find_a_union(int x) { if(find_and_union[x] == x) return x; return find_and_union[x] = find_a_union(find_and_union[x]); } int index = 0; void dfs(int x, int h=0) { LCA_id[x] = index; LCA[0][index++] = h; for(int i = 0; i < tree[x].size(); i++) { dfs(tree[x][i],h+1); LCA[0][index++] = h; } } int min(int a, int b) {return (a<b)?a:b; } struct reaction { int a, b, v, id; } queue[500010]; bool operator<(reaction a, reaction b) { if(a.v == b.v) return a.id < b.id; return a.v > b.v; } int main() { int n, m, k; scanf("%d%d%d", &n, &m, &k); for(int i = 0; i <= n; i++) find_and_union[i] = i; for(int i = 1; i <= n; i++) scanf("%d", vol+i); int extent = n+1; for(int i = 0; i < m; i++) { int x,y; scanf("%d%d", &x, &y); int _x = find_a_union(x), _y = find_a_union(y); tree[extent].resize(2); tree[extent][0] = _x; tree[extent][1] = _y; find_and_union[_x] = extent; find_and_union[_y] = extent; find_and_union[extent] = extent; extent++; } for(int i = 1; i < extent; i++) if(!gotit[find_a_union(i)]) { tree[0].push_back(find_a_union(i)); gotit[find_a_union(i)] = 1; } dfs(0); for(int i = 1; (1<<i) <= index; i++) { int off = 1<<i; for(int j = 0; j <= index-off; j++) LCA[i][j] = min(LCA[i-1][j],LCA[i-1][j+(off>>1)]); } for(int i = 0; i < k; i++) { queue[i].id = i; scanf("%d%d", &(queue[i].a), &(queue[i].b)); int id_a = LCA_id[queue[i].a], id_b = LCA_id[queue[i].b]; if(id_a > id_b) {int c = id_a; id_a = id_b; id_b = c;} int off = 0; while(id_b - id_a + 1 >= (1<<off)) off++; off--; queue[i].v = min(LCA[off][id_a], LCA[off][id_b - (1<<off)+1]); } std::sort(queue,queue+k); long long res = 0; for(int i = 0; i < k && queue[i].v; i++) { int react = min(vol[queue[i].a],vol[queue[i].b]); res += react*2; vol[queue[i].a]-=react; vol[queue[i].b]-=react; } printf("%lld\n", res); return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | #include<cstdio> #include<vector> #include<algorithm> enum { MAX = 200010*2, }; int vol[MAX]; std::vector<int> tree[MAX]; int find_and_union[MAX]; bool gotit[MAX]; int LCA[20][MAX*2]; int LCA_id[MAX]; int find_a_union(int x) { if(find_and_union[x] == x) return x; return find_and_union[x] = find_a_union(find_and_union[x]); } int index = 0; void dfs(int x, int h=0) { LCA_id[x] = index; LCA[0][index++] = h; for(int i = 0; i < tree[x].size(); i++) { dfs(tree[x][i],h+1); LCA[0][index++] = h; } } int min(int a, int b) {return (a<b)?a:b; } struct reaction { int a, b, v, id; } queue[500010]; bool operator<(reaction a, reaction b) { if(a.v == b.v) return a.id < b.id; return a.v > b.v; } int main() { int n, m, k; scanf("%d%d%d", &n, &m, &k); for(int i = 0; i <= n; i++) find_and_union[i] = i; for(int i = 1; i <= n; i++) scanf("%d", vol+i); int extent = n+1; for(int i = 0; i < m; i++) { int x,y; scanf("%d%d", &x, &y); int _x = find_a_union(x), _y = find_a_union(y); tree[extent].resize(2); tree[extent][0] = _x; tree[extent][1] = _y; find_and_union[_x] = extent; find_and_union[_y] = extent; find_and_union[extent] = extent; extent++; } for(int i = 1; i < extent; i++) if(!gotit[find_a_union(i)]) { tree[0].push_back(find_a_union(i)); gotit[find_a_union(i)] = 1; } dfs(0); for(int i = 1; (1<<i) <= index; i++) { int off = 1<<i; for(int j = 0; j <= index-off; j++) LCA[i][j] = min(LCA[i-1][j],LCA[i-1][j+(off>>1)]); } for(int i = 0; i < k; i++) { queue[i].id = i; scanf("%d%d", &(queue[i].a), &(queue[i].b)); int id_a = LCA_id[queue[i].a], id_b = LCA_id[queue[i].b]; if(id_a > id_b) {int c = id_a; id_a = id_b; id_b = c;} int off = 0; while(id_b - id_a + 1 >= (1<<off)) off++; off--; queue[i].v = min(LCA[off][id_a], LCA[off][id_b - (1<<off)+1]); } std::sort(queue,queue+k); long long res = 0; for(int i = 0; i < k && queue[i].v; i++) { int react = min(vol[queue[i].a],vol[queue[i].b]); res += react*2; vol[queue[i].a]-=react; vol[queue[i].b]-=react; } printf("%lld\n", res); return 0; } |