#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
#define ll long long
#define INF 2000000000
int n,m,k,g[200001];
struct fiolka{int r,krok; vector<int> d;} f[200001];
struct para{int i,krok,c,d;} p[500001];
bool fc(const para &a, const para &b) {
if (a.krok==b.krok) return a.i<b.i;
return a.krok<b.krok;
}
vector<int> reagenci[200001];
int col[200001];
void TarjanOLCA(int u);
int main(int argc, char** argv) {
ios_base::sync_with_stdio(0);
cin >> n >> m >> k;
for (int i=1;i<=n;i++) cin >> g[i];
for (int i=1;i<=m;i++) {
int a,b;
cin >> a >> b;
f[a].r=b;
f[a].krok=i;
f[b].d.push_back(a);
}
for (int i=1;i<=k;i++) {
int c,d;
cin >> c >> d;
p[i].c=c;p[i].d=d; p[i].i=i; p[i].krok=INF;
reagenci[c].push_back(i);
reagenci[d].push_back(i);
}
for (int i=1;i<=n;i++) {
if (f[i].r==0)
TarjanOLCA(i);
}
sort(p+1,p+k+1,fc);
//for (int i=1;i<=k;i++) cout << p[i].i << ": " << p[i].krok << '\n';
ll ans=0;
for (int i=1;i<=k && p[i].krok<INF;i++) {
int gmin=min(g[p[i].c],g[p[i].d]);
if (gmin>0) {
ans+=2*gmin;
g[p[i].c]-=gmin;
g[p[i].d]-=gmin;
}
}
cout << ans << '\n';
return 0;
}
struct zr{int parent,edge;} tab[200001];
void MakeSet(int x) {
tab[x].parent = x;
tab[x].edge = 0;
}
int Find(int x,int &edge) {
if (tab[x].parent == x) {
return x;
}
else {
edge = tab[x].edge;
int r = Find(tab[x].parent,edge);
tab[x].edge = edge;
tab[x].parent =r;
//cout <<"dla " << x << " p=" << r << " e=" << edge << "\n";
return r;
}
}
void Union(int x, int y){
int ex,ey;
int xRoot = Find(x,ex);
int yRoot = Find(y,ey);
if (xRoot != yRoot) {
tab[yRoot].parent = xRoot;
tab[yRoot].edge = f[yRoot].krok;
}
}
vector<int> szuk[200001];
void TarjanOLCA(int u) {
MakeSet(u);
//u.ancestor := u
//dla każdego v należącego do u.children wykonaj
for (int i=0;i<f[u].d.size();i++) {
int v=f[u].d[i];
TarjanOLCA(v);
Union(u,v);
//cout << "dodalem " << v << " do " << u << " p=" << tab[v].parent << " e=" << tab[v].edge << '\n';
//Find(u).ancestor := u
}
col[u] = 1;
//cout << u << " gotowe" << '\n';
//dla każdego v takiego, że {u,v} należy do P wykonaj
for (int i=0;i<reagenci[u].size();i++) {
int k=reagenci[u][i];
int v=p[k].c;
if (v==u) v=p[k].d;
if (col[v] == 1) {
int e;
//cout << "szukam wspólnego przodka dla " << u << " i " << v << "\n";
szuk[Find(v,e)].push_back(k);
}
}
for (int i=0;i<szuk[u].size();i++) {
int k = szuk[u][i];
int e;
Find(p[k].c,e); Find(p[k].d,e);
//cout << " mam dla k=" << k << " c.edge=" << tab[p[k].c].edge << " d.edge=" << tab[p[k].d].edge << '\n';
p[k].krok=max(tab[p[k].c].edge,tab[p[k].d].edge);
}
}
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 | #include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <set> using namespace std; #define ll long long #define INF 2000000000 int n,m,k,g[200001]; struct fiolka{int r,krok; vector<int> d;} f[200001]; struct para{int i,krok,c,d;} p[500001]; bool fc(const para &a, const para &b) { if (a.krok==b.krok) return a.i<b.i; return a.krok<b.krok; } vector<int> reagenci[200001]; int col[200001]; void TarjanOLCA(int u); int main(int argc, char** argv) { ios_base::sync_with_stdio(0); cin >> n >> m >> k; for (int i=1;i<=n;i++) cin >> g[i]; for (int i=1;i<=m;i++) { int a,b; cin >> a >> b; f[a].r=b; f[a].krok=i; f[b].d.push_back(a); } for (int i=1;i<=k;i++) { int c,d; cin >> c >> d; p[i].c=c;p[i].d=d; p[i].i=i; p[i].krok=INF; reagenci[c].push_back(i); reagenci[d].push_back(i); } for (int i=1;i<=n;i++) { if (f[i].r==0) TarjanOLCA(i); } sort(p+1,p+k+1,fc); //for (int i=1;i<=k;i++) cout << p[i].i << ": " << p[i].krok << '\n'; ll ans=0; for (int i=1;i<=k && p[i].krok<INF;i++) { int gmin=min(g[p[i].c],g[p[i].d]); if (gmin>0) { ans+=2*gmin; g[p[i].c]-=gmin; g[p[i].d]-=gmin; } } cout << ans << '\n'; return 0; } struct zr{int parent,edge;} tab[200001]; void MakeSet(int x) { tab[x].parent = x; tab[x].edge = 0; } int Find(int x,int &edge) { if (tab[x].parent == x) { return x; } else { edge = tab[x].edge; int r = Find(tab[x].parent,edge); tab[x].edge = edge; tab[x].parent =r; //cout <<"dla " << x << " p=" << r << " e=" << edge << "\n"; return r; } } void Union(int x, int y){ int ex,ey; int xRoot = Find(x,ex); int yRoot = Find(y,ey); if (xRoot != yRoot) { tab[yRoot].parent = xRoot; tab[yRoot].edge = f[yRoot].krok; } } vector<int> szuk[200001]; void TarjanOLCA(int u) { MakeSet(u); //u.ancestor := u //dla każdego v należącego do u.children wykonaj for (int i=0;i<f[u].d.size();i++) { int v=f[u].d[i]; TarjanOLCA(v); Union(u,v); //cout << "dodalem " << v << " do " << u << " p=" << tab[v].parent << " e=" << tab[v].edge << '\n'; //Find(u).ancestor := u } col[u] = 1; //cout << u << " gotowe" << '\n'; //dla każdego v takiego, że {u,v} należy do P wykonaj for (int i=0;i<reagenci[u].size();i++) { int k=reagenci[u][i]; int v=p[k].c; if (v==u) v=p[k].d; if (col[v] == 1) { int e; //cout << "szukam wspólnego przodka dla " << u << " i " << v << "\n"; szuk[Find(v,e)].push_back(k); } } for (int i=0;i<szuk[u].size();i++) { int k = szuk[u][i]; int e; Find(p[k].c,e); Find(p[k].d,e); //cout << " mam dla k=" << k << " c.edge=" << tab[p[k].c].edge << " d.edge=" << tab[p[k].d].edge << '\n'; p[k].krok=max(tab[p[k].c].edge,tab[p[k].d].edge); } } |
English