#include <iostream> #include <vector> #include <cstdio> #define ST first #define ND second #define MP make_pair #define PB push_back using namespace std; const int N = 200010; vector<int> graf[N]; vector<pair<int, int> > pary[N]; int f[N][20], sp[N], ile[N], t1[N], t2[N], czas; bool korzen[N]; long long int res; int n, m, k, a, b; void dfs(int v) { t1[v] = czas++; for (int i=0; i<graf[v].size(); i++) { f[graf[v][i]][0] = v; sp[graf[v][i]] = sp[v]; dfs(graf[v][i]); } t2[v] = czas++; } void dfs2(int v) { for (int i=0; i<graf[v].size(); i++) { dfs2(graf[v][i]); } for (int i=0; i<pary[v].size(); i++) { int a = pary[v][i].ST; int b = pary[v][i].ND; int mi = min(ile[a], ile[b]); res += mi; ile[a] -= mi; ile[b] -= mi; } } bool czy_potomek(int a, int b) { // czy a nad b return t1[a] <= t1[b] && t2[a] >= t2[b]; } int lca(int a, int b) { int skok = 18; if (czy_potomek(a, b)) { return a; } if (czy_potomek(b, a)) { return b; } while (skok >= 0) { if (czy_potomek(f[a][skok], b)) { skok--; } else { a = f[a][skok]; } } return f[a][0]; } int main() { scanf("%d %d %d", &n, &m, &k); for (int i=1; i<=n; i++) { scanf("%d", &ile[i]); korzen[i] = true; } for (int i=1; i<=m; i++) { scanf("%d %d", &a, &b); graf[b].PB(a); korzen[a] = false; } for (int i=1; i<=n; i++) { if (korzen[i]) { f[i][0] = i; sp[i] = i; dfs(i); } } for (int i=1; i<=18; i++) { for (int j=1; j<=n; j++) { f[j][i] = f[f[j][i-1]][i-1]; } } for (int i=1; i<=k; i++) { scanf("%d %d", &a, &b); if (sp[a] == sp[b]) { int u = lca(a, b); pary[u].PB(MP(a, b)); } } for (int i=1; i<=n; i++) { if (korzen[i]) { dfs2(i); } } printf("%lld\n", res * 2); 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 | #include <iostream> #include <vector> #include <cstdio> #define ST first #define ND second #define MP make_pair #define PB push_back using namespace std; const int N = 200010; vector<int> graf[N]; vector<pair<int, int> > pary[N]; int f[N][20], sp[N], ile[N], t1[N], t2[N], czas; bool korzen[N]; long long int res; int n, m, k, a, b; void dfs(int v) { t1[v] = czas++; for (int i=0; i<graf[v].size(); i++) { f[graf[v][i]][0] = v; sp[graf[v][i]] = sp[v]; dfs(graf[v][i]); } t2[v] = czas++; } void dfs2(int v) { for (int i=0; i<graf[v].size(); i++) { dfs2(graf[v][i]); } for (int i=0; i<pary[v].size(); i++) { int a = pary[v][i].ST; int b = pary[v][i].ND; int mi = min(ile[a], ile[b]); res += mi; ile[a] -= mi; ile[b] -= mi; } } bool czy_potomek(int a, int b) { // czy a nad b return t1[a] <= t1[b] && t2[a] >= t2[b]; } int lca(int a, int b) { int skok = 18; if (czy_potomek(a, b)) { return a; } if (czy_potomek(b, a)) { return b; } while (skok >= 0) { if (czy_potomek(f[a][skok], b)) { skok--; } else { a = f[a][skok]; } } return f[a][0]; } int main() { scanf("%d %d %d", &n, &m, &k); for (int i=1; i<=n; i++) { scanf("%d", &ile[i]); korzen[i] = true; } for (int i=1; i<=m; i++) { scanf("%d %d", &a, &b); graf[b].PB(a); korzen[a] = false; } for (int i=1; i<=n; i++) { if (korzen[i]) { f[i][0] = i; sp[i] = i; dfs(i); } } for (int i=1; i<=18; i++) { for (int j=1; j<=n; j++) { f[j][i] = f[f[j][i-1]][i-1]; } } for (int i=1; i<=k; i++) { scanf("%d %d", &a, &b); if (sp[a] == sp[b]) { int u = lca(a, b); pary[u].PB(MP(a, b)); } } for (int i=1; i<=n; i++) { if (korzen[i]) { dfs2(i); } } printf("%lld\n", res * 2); return 0; } |