Cod sursa(job #52687)

Utilizator scapryConstantin Berzan scapry Data 19 aprilie 2007 18:27:07
Problema Cerere Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.41 kb
#include <assert.h>
#include <stdio.h>
#include <string.h>

enum { maxn = 100001 };

struct ls
{
	int n;
	ls *next;
} *lst[maxn];

int n;
int dad[maxn];
int want[maxn];
int go[maxn]; //go[i] = the want[i]-th parent of i
bool v[maxn];
int stack[maxn], depth;

void df(int node)
{
	assert(!v[node]);
	v[node]++;
	stack[depth] = node;
	
	assert(depth >= want[node]);
	go[node] = stack[ depth - want[node] ];

	if(want[node] != 0) assert(go[node] != node); //could be better

	depth++;
	for(ls *p = lst[node]; p; p = p->next)
		df(p->n);
	depth--;
}

void calc_go()
{
	int i;

	for(i = 0; i < n; i++)
		if(dad[i] == -1)
		{
			df(i);
			break;
		}

	assert(i != n);

	for(i = 0; i < n; i++)
		assert(v[i]);
}

void add(int from, int to)
{
	ls *p = new ls;
	p->n = to;
	p->next = lst[from];
	lst[from] = p;
}

int main()
{
	int i, a, b, ans, pos;
	FILE *f = fopen("cerere.in", "r");
	if(!f) return 1;

	fscanf(f, "%d", &n);
	
	for(i = 0; i < n; i++)
		fscanf(f, "%d", &want[i]);

	memset(dad, 0xFF, sizeof(dad)); //-1

	for(i = 0; i < n - 1; i++)
	{
		fscanf(f, "%d%d", &a, &b);
		a--; b--;
		assert(dad[b] == -1);
		dad[b] = a;
		add(a, b);
	}

	fclose(f);
	f = fopen("cerere.out", "w");
	if(!f) return 1;

	calc_go();

	for(i = 0; i < n; i++)
	{
		ans = 0;
		pos = i;
		
		while(want[pos] != 0) //must go up
		{
			pos = go[pos];
			ans++;
		}

		if(i != 0) fprintf(f, " ");
		fprintf(f, "%d", ans);
	}

	fprintf(f, "\n");
	fclose(f);
	return 0;
}