Cod sursa(job #586113)

Utilizator ciprianfFarcasanu Alexandru Ciprian ciprianf Data 30 aprilie 2011 13:44:26
Problema Guvern Scor 0
Compilator cpp Status done
Runda Algoritmiada 2011, Runda Finală, Clasele 10-12 Marime 2.04 kb
#include <stdio.h>
#include <vector>
#include <set>
using namespace std;
#define N_MAX 200010
#define mp make_pair
#define FOR(i, v) for(vector<int>::iterator i = v.begin(); i != v.end(); ++i)
vector <int> G[N_MAX], C[N_MAX];
set < pair <int, int> > H;
set < pair <int, int> >::iterator it;
int A[N_MAX];
int v[N_MAX], coresp[N_MAX], cost[N_MAX];
int in[N_MAX], out[N_MAX], up[N_MAX];
bool viz[N_MAX];
int n, k;
int val, poz;

void check(int x) {
    it = H.upper_bound(mp(v[x],0));
    if(it==H.end()) return;
    coresp[x] = it->second;
    if(it->second) C[it->second].push_back(x);
    if(it->first == v[x]) H.erase(it);
}
void df(int x) {
    viz[x] = 1;
    check(x);
    H.insert(mp(v[x],x));
    in[x] = ++k;
    FOR(i, G[x])
        if(!viz[*i])
            df(*i);

    H.erase(mp(v[x],x));
    viz[x] = 0;
    out[x] = k;
}
void make_c(int x) {
    viz[x] = 1;
    FOR(i, G[x])
        if(!viz[*i])
            make_c(*i);
    A[x] = 1;
    FOR(i, C[x])
        A[x] += A[*i];
    int p = 0;
    FOR(i, G[x])
        if(!viz[*i]) {
            int p1 = p, s = 0;
            while(p1 < C[x].size() && in[C[x][p1]] <= out[*i]) s += A[C[x][p1]], p1++;
            while(p < C[x].size() && in[C[x][p]] <= out[*i]) cost[C[x][p]] = A[x]-s-1, p++;
        }
    viz[x] = 0;
}
void make_up(int x) {
    if(x == 1 || x == 0) return;
    if(!up[coresp[x]])
        make_up(coresp[x]);
    up[x] = cost[x] + up[coresp[x]]+1;
}
int main() {
    freopen("guvern.in" ,"r", stdin);
    freopen("guvern.out", "w", stdout);
    scanf("%d", &n);
    for(int i = 1; i < n; ++i) {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    for(int i = 1; i <= n; ++i)
        scanf("%d", &v[i]);
    df(1);

    make_c(1);

   /* for(int i = 1; i <= n; ++i)
        printf("%d %d %d\n",i, coresp[i], cost[i]);*/
    for(int i = 1; i <= n; ++i)
        if(!up[i]) make_up(i);
    int sol = 0;
    for(int i = 1; i <= n; ++i)
        if(sol < cost[i] + up[coresp[i]])
            sol = cost[i] + up[coresp[i]];
    printf("%d\n", sol+1);
}