#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
// process3 oraz query ze strony http://www.topcoder.com/tc?d1=tutorials&d2=lowestCommonAncestor&module=Static
int P[400100][20];
void process3(int N, int* T)
{
int i, j;
//we initialize every element in P with -1
for (i = 1; i <= N; i++)
for (j = 0; 1 << j < N; j++)
P[i][j] = -1;
//the first ancestor of every node i is T[i]
for (i = 1; i <= N; i++)
P[i][0] = T[i];
//bottom up dynamic programing
for (j = 1; 1 << j < N; j++)
for (i = 1; i <= N; i++)
if (P[i][j - 1] != -1)
P[i][j] = P[P[i][j - 1]][j - 1];
//for (int i=1;i<=N;i++) {for (int j=0;j<N;j++) printf("%d ", P[i][j]); printf("\n");}
}
int query(int N, int * T, int *L, int p, int q)
{
int tmp, log, i;
//if p is situated on a higher level than q then we swap them
if (L[p] < L[q])
tmp = p, p = q, q = tmp;
//we compute the value of [log(L[p)]
for (log = 1; 1 << log <= L[p]; log++);
log--;
//we find the ancestor of node p situated on the same level
//with q using the values in P
for (i = log; i >= 0; i--)
if (L[p] - (1 << i) >= L[q])
p = P[p][i];
if (p == q)
return p;
//we compute LCA(p, q) using the values in P
for (i = log; i >= 0; i--)
if (P[p][i] != -1 && P[p][i] != P[q][i])
p = P[p][i], q = P[q][i];
return T[p];
}
int main() {
int n,m,k;
scanf("%d %d %d", &n, &m, &k);
long long g[n+5];
for (int i=1;i<=n;i++) scanf("%lld", g+i);
long long result = 0;
int* level = new int[n+m+5];
int* root = new int[n+m+5];
int* parent = new int[n+m+5];
int* mapa = new int[n+10];
int* dziecko_1 = new int[n+m+5];
int* dziecko_2 = new int[n+m+5];
for (int i=0;i<=n+m;i++) {level[i]=0; dziecko_1[i]=-1; dziecko_2[i] = -1; parent[i]=-1;}
for (int i=1;i<=n;i++) mapa[i] = i;
// budujemy drzewo
for (int i=1;i<=m;i++) {
int a, b;
scanf("%d %d", &a, &b);
parent[mapa[a]]=n+i;
parent[mapa[b]]=n+i;
dziecko_1[n+i] = mapa[a];
dziecko_2[n+i] = mapa[b];
mapa[b]=n+i;
}
//printf("Drzewo: "); for (int i=1;i<=n+m;i++) printf("%d ", parent[i]); printf("\n");
// przypisanie poziomu (BFS)
queue<int> q;
for (int i=1;i<=n+m;i++) if (parent[i]==-1) {q.push(i); level[i]=1;}
while (!q.empty()) {
int node = q.front();
q.pop();
if (level[node] == 0) level[node] = level[parent[node]] + 1;
if (dziecko_1[node] != -1) q.push(dziecko_1[node]);
if (dziecko_2[node] != -1) q.push(dziecko_2[node]);
}
//printf("Poziomy: "); for (int i=1;i<=n+m;i++) printf("%d ", level[i]); printf("\n");
//szukamy LCA i liczymy wynik
process3(n+m, parent);
vector< pair<pair<int,int>, pair<int, int> > > reakcje;
for (int i=0;i<k;i++) {
int c, d;
scanf("%d %d", &c, &d);
int lca = query(n+m, parent, level, c, d);
//printf("LCA(%d, %d) = %d\n", c, d, lca);
reakcje.push_back(make_pair(make_pair(lca, i), make_pair(c, d)));
}
sort(reakcje.begin(), reakcje.end());
for (int i=0;i<k;i++) {
if (reakcje[i].first.first!=-1) {
long long osad = min(g[reakcje[i].second.first], g[reakcje[i].second.second]);
//printf("osad(%d, %d): %lld\n", reakcje[i].second.first, reakcje[i].second.second, osad);
result += 2*osad;
g[reakcje[i].second.first] -= osad;
g[reakcje[i].second.second] -= osad;
}
}
printf("%lld\n", result);
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 | #include <cstdio> #include <queue> #include <vector> #include <algorithm> using namespace std; // process3 oraz query ze strony http://www.topcoder.com/tc?d1=tutorials&d2=lowestCommonAncestor&module=Static int P[400100][20]; void process3(int N, int* T) { int i, j; //we initialize every element in P with -1 for (i = 1; i <= N; i++) for (j = 0; 1 << j < N; j++) P[i][j] = -1; //the first ancestor of every node i is T[i] for (i = 1; i <= N; i++) P[i][0] = T[i]; //bottom up dynamic programing for (j = 1; 1 << j < N; j++) for (i = 1; i <= N; i++) if (P[i][j - 1] != -1) P[i][j] = P[P[i][j - 1]][j - 1]; //for (int i=1;i<=N;i++) {for (int j=0;j<N;j++) printf("%d ", P[i][j]); printf("\n");} } int query(int N, int * T, int *L, int p, int q) { int tmp, log, i; //if p is situated on a higher level than q then we swap them if (L[p] < L[q]) tmp = p, p = q, q = tmp; //we compute the value of [log(L[p)] for (log = 1; 1 << log <= L[p]; log++); log--; //we find the ancestor of node p situated on the same level //with q using the values in P for (i = log; i >= 0; i--) if (L[p] - (1 << i) >= L[q]) p = P[p][i]; if (p == q) return p; //we compute LCA(p, q) using the values in P for (i = log; i >= 0; i--) if (P[p][i] != -1 && P[p][i] != P[q][i]) p = P[p][i], q = P[q][i]; return T[p]; } int main() { int n,m,k; scanf("%d %d %d", &n, &m, &k); long long g[n+5]; for (int i=1;i<=n;i++) scanf("%lld", g+i); long long result = 0; int* level = new int[n+m+5]; int* root = new int[n+m+5]; int* parent = new int[n+m+5]; int* mapa = new int[n+10]; int* dziecko_1 = new int[n+m+5]; int* dziecko_2 = new int[n+m+5]; for (int i=0;i<=n+m;i++) {level[i]=0; dziecko_1[i]=-1; dziecko_2[i] = -1; parent[i]=-1;} for (int i=1;i<=n;i++) mapa[i] = i; // budujemy drzewo for (int i=1;i<=m;i++) { int a, b; scanf("%d %d", &a, &b); parent[mapa[a]]=n+i; parent[mapa[b]]=n+i; dziecko_1[n+i] = mapa[a]; dziecko_2[n+i] = mapa[b]; mapa[b]=n+i; } //printf("Drzewo: "); for (int i=1;i<=n+m;i++) printf("%d ", parent[i]); printf("\n"); // przypisanie poziomu (BFS) queue<int> q; for (int i=1;i<=n+m;i++) if (parent[i]==-1) {q.push(i); level[i]=1;} while (!q.empty()) { int node = q.front(); q.pop(); if (level[node] == 0) level[node] = level[parent[node]] + 1; if (dziecko_1[node] != -1) q.push(dziecko_1[node]); if (dziecko_2[node] != -1) q.push(dziecko_2[node]); } //printf("Poziomy: "); for (int i=1;i<=n+m;i++) printf("%d ", level[i]); printf("\n"); //szukamy LCA i liczymy wynik process3(n+m, parent); vector< pair<pair<int,int>, pair<int, int> > > reakcje; for (int i=0;i<k;i++) { int c, d; scanf("%d %d", &c, &d); int lca = query(n+m, parent, level, c, d); //printf("LCA(%d, %d) = %d\n", c, d, lca); reakcje.push_back(make_pair(make_pair(lca, i), make_pair(c, d))); } sort(reakcje.begin(), reakcje.end()); for (int i=0;i<k;i++) { if (reakcje[i].first.first!=-1) { long long osad = min(g[reakcje[i].second.first], g[reakcje[i].second.second]); //printf("osad(%d, %d): %lld\n", reakcje[i].second.first, reakcje[i].second.second, osad); result += 2*osad; g[reakcje[i].second.first] -= osad; g[reakcje[i].second.second] -= osad; } } printf("%lld\n", result); return 0; } |
English