#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; } |
English