#include <cstdio> #include <vector> #include <algorithm> struct Reaction { bool operator<(const Reaction &rhs) const { return (time != rhs.time)?(time<rhs.time):(order<rhs.order); } int time; int order; int a; int b; }; int N,STEPS,PAIRS; int weight[200010]; int fau_p[200010]; int fau_w[200010]; int root[200010]; int nodes; int parent[400010][20]; bool visited[400010]; int rtim[400010]; int left[400010], right[400010]; int dfs_d[400010], dfs_p[400010]; std::vector<Reaction> reactions; inline int fau_find(int x) { return (fau_p[x] < 0) ? x : (fau_p[x] = fau_find(fau_p[x])); } inline void fau_union(int x, int y) { if ((x = fau_find(x)) == (y = fau_find(y))) return; if (fau_w[x] > fau_w[y]) fau_p[y] = x; else fau_p[x] = y; if (fau_w[x] == fau_w[y]) fau_w[y]++; } inline void build(int r) { static int cnt = 0; int level = 1; dfs_d[r] = ++cnt; while (parent[r][level-1] > 0) { parent[r][level] = parent[parent[r][level-1]][level-1]; ++level; } if (left[r]>0) build(left[r]); if (right[r]>0) build(right[r]); dfs_p[r] = ++cnt; } inline int getTime(int a, int b) { if (dfs_d[a] < dfs_d[b] && dfs_p[a] > dfs_p[b]) return rtim[a]; if (dfs_d[b] < dfs_d[a] && dfs_p[b] > dfs_p[a]) return rtim[b]; int l = 0, r = 19; while (l < r) { int s = l + (r-l+1)/2; int m = parent[a][s]; if (m == 0 || (dfs_d[m] < dfs_d[b] && dfs_p[m] > dfs_p[b])) r = s-1; else l = s; } return getTime(parent[a][l],b); } int main() { scanf("%d %d %d",&N,&STEPS,&PAIRS); for (int i=1; i<=N; ++i) { scanf("%d",&weight[i]); fau_p[i] = fau_w[i] = -1; root[i] = i; } nodes = N; for (int i=1; i<=STEPS; ++i) { int a,b; scanf("%d %d",&a,&b); int l = fau_find(a); int r = fau_find(b); ++nodes; parent[root[l]][0] = parent[root[r]][0] = nodes; left[nodes] = root[l]; right[nodes] = root[r]; fau_union(l,r); root[fau_find(l)] = nodes; rtim[nodes] = i; } //budowa struktury pomocnicznej dla drzewa for (int i=1; i<=N; ++i) { int r = root[fau_find(i)]; if (!visited[r]) { visited[r] = true; build(r); } } for (int i=1; i<=PAIRS; ++i) { int c,d; scanf("%d %d",&c,&d); if (fau_find(c) == fau_find(d)) { Reaction r; r.time = getTime(c,d); r.order = i; r.a = c; r.b = d; reactions.push_back(r); } } std::sort(reactions.begin(), reactions.end()); long long int res = 0; for (int i=0; i<reactions.size(); ++i) { int o = std::min(weight[reactions[i].a], weight[reactions[i].b]); res += o+o; weight[reactions[i].a] -= o; weight[reactions[i].b] -= o; } 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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | #include <cstdio> #include <vector> #include <algorithm> struct Reaction { bool operator<(const Reaction &rhs) const { return (time != rhs.time)?(time<rhs.time):(order<rhs.order); } int time; int order; int a; int b; }; int N,STEPS,PAIRS; int weight[200010]; int fau_p[200010]; int fau_w[200010]; int root[200010]; int nodes; int parent[400010][20]; bool visited[400010]; int rtim[400010]; int left[400010], right[400010]; int dfs_d[400010], dfs_p[400010]; std::vector<Reaction> reactions; inline int fau_find(int x) { return (fau_p[x] < 0) ? x : (fau_p[x] = fau_find(fau_p[x])); } inline void fau_union(int x, int y) { if ((x = fau_find(x)) == (y = fau_find(y))) return; if (fau_w[x] > fau_w[y]) fau_p[y] = x; else fau_p[x] = y; if (fau_w[x] == fau_w[y]) fau_w[y]++; } inline void build(int r) { static int cnt = 0; int level = 1; dfs_d[r] = ++cnt; while (parent[r][level-1] > 0) { parent[r][level] = parent[parent[r][level-1]][level-1]; ++level; } if (left[r]>0) build(left[r]); if (right[r]>0) build(right[r]); dfs_p[r] = ++cnt; } inline int getTime(int a, int b) { if (dfs_d[a] < dfs_d[b] && dfs_p[a] > dfs_p[b]) return rtim[a]; if (dfs_d[b] < dfs_d[a] && dfs_p[b] > dfs_p[a]) return rtim[b]; int l = 0, r = 19; while (l < r) { int s = l + (r-l+1)/2; int m = parent[a][s]; if (m == 0 || (dfs_d[m] < dfs_d[b] && dfs_p[m] > dfs_p[b])) r = s-1; else l = s; } return getTime(parent[a][l],b); } int main() { scanf("%d %d %d",&N,&STEPS,&PAIRS); for (int i=1; i<=N; ++i) { scanf("%d",&weight[i]); fau_p[i] = fau_w[i] = -1; root[i] = i; } nodes = N; for (int i=1; i<=STEPS; ++i) { int a,b; scanf("%d %d",&a,&b); int l = fau_find(a); int r = fau_find(b); ++nodes; parent[root[l]][0] = parent[root[r]][0] = nodes; left[nodes] = root[l]; right[nodes] = root[r]; fau_union(l,r); root[fau_find(l)] = nodes; rtim[nodes] = i; } //budowa struktury pomocnicznej dla drzewa for (int i=1; i<=N; ++i) { int r = root[fau_find(i)]; if (!visited[r]) { visited[r] = true; build(r); } } for (int i=1; i<=PAIRS; ++i) { int c,d; scanf("%d %d",&c,&d); if (fau_find(c) == fau_find(d)) { Reaction r; r.time = getTime(c,d); r.order = i; r.a = c; r.b = d; reactions.push_back(r); } } std::sort(reactions.begin(), reactions.end()); long long int res = 0; for (int i=0; i<reactions.size(); ++i) { int o = std::min(weight[reactions[i].a], weight[reactions[i].b]); res += o+o; weight[reactions[i].a] -= o; weight[reactions[i].b] -= o; } printf("%lld\n", res); return 0; } |