Cod sursa(job #585929)

Utilizator savimSerban Andrei Stan savim Data 30 aprilie 2011 12:43:09
Problema Guvern Scor 0
Compilator cpp Status done
Runda Algoritmiada 2011, Runda Finală, Clasele 10-12 Marime 2.71 kb
#include <stdio.h>
#include <set>
#include <vector>
#include <algorithm>

using namespace std;

#define MAX_N 200010

#define mp make_pair

int n, m, sol, p2, k;

int anc[MAX_N], use[MAX_N], cost[MAX_N], c[MAX_N], niv[MAX_N];

int tata[20][MAX_N];

int tata2[MAX_N], use2[MAX_N], next[MAX_N], d[MAX_N];

typedef set <pair <int, int> > MYSET;

MYSET s;

vector <int> G[MAX_N], vine[MAX_N], tree[MAX_N];

inline int get_father(int x, int niv) {
	for (int i = p2; i >= 0; i--)
		if ((1 << i) <= niv) {
			x = tata[i][x];
        	niv -= 1 << i;
		}

	return x;
}

void build_tree(int init, int nod, int start, int stop) {
	if (start > stop)
		return;

	int fiu = vine[init][start];

	if (niv[fiu] > niv[nod] && get_father(fiu, niv[fiu] - niv[nod]) == nod) {

		tree[nod].push_back(fiu);
		tree[fiu].push_back(nod); 

		tata2[fiu] = nod;

		build_tree(init, fiu, start + 1, stop);
	}
	else
		build_tree(init, tata2[nod], start, stop);
}

int dfs2(int nod) {
	use2[nod] = 1;

	int len = tree[nod].size() - 1;

	if (len >= 0) {
		for (int i = len - 1; i >= 0; i--)
			if (use2[tree[nod][i]] == 0)
				next[tree[nod][i]] = tree[nod][i + 1];
		next[tree[nod][len]] = next[nod];
	}

	int ans = d[nod];

	d[next[nod]] = max(d[next[nod]], d[nod] + c[nod]);

	ans = max(ans, d[next[nod]]);

	for (int i = 0; i <= len; i++)
		if (use2[tree[nod][i]] == 0) {
			dfs2(tree[nod][i]);

			ans = max(ans, d[tree[nod][i]]);
		}

	return ans;
}

void dfs(int nod) {
	use[nod] = 1;

	for (int i = 1; i <= p2; i++)
		tata[i][nod] = tata[i - 1][tata[i - 1][nod]];

	MYSET::iterator it = s.upper_bound(make_pair(cost[nod], nod)); //gasesc primul cost > costul curent
	if (it != s.end()) 
    	anc[nod] = it->second;
	s.insert(mp(cost[nod], nod));

	if (anc[nod])
		vine[anc[nod]].push_back(nod);

	for (vector <int>::iterator Git = G[nod].begin(); Git != G[nod].end(); ++Git)
		if (use[*Git] == 0) {
			niv[*Git] = niv[nod] + 1;
			tata[0][*Git] = nod;
			dfs(*Git);
		}

	it = s.find(make_pair(cost[nod], nod));
	s.erase(it);

	int len = vine[nod].size() - 1;
	for (int i = 0; i <= len; i++) {
		vector <int> ().swap(tree[vine[nod][i]]);
    	tata2[vine[nod][i]] = use2[vine[nod][i]] = d[vine[nod][i]] = 0;
	}

	build_tree(nod, nod, 0, vine[nod].size() - 1); //construiesc arborele micut

	next[nod] = n + 1;
	c[nod] = dfs2(nod) + 1;

	sol = max(sol, c[nod]);
}

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", &cost[i]);

	for (int i = 0;; i++)
		if ((1 << i) >= n) {
        	p2 = i;
			break;
		}

	cost[0] = -2000000000; niv[1] = 1;
	dfs(1);

	printf("%d\n", sol);

	return 0;
}