Cod sursa(job #222689)

Utilizator savimSerban Andrei Stan savim Data 24 noiembrie 2008 17:18:54
Problema Radiatie Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.68 kb
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

#define MAX_L 32010
#define inf (1 << 31) - 1

int fol[MAX_L], tata[MAX_L], nivel[MAX_L];
int n, m, i, j, k, val, p , q, nr, sol, X, Y;
int euler[2 * MAX_L], adanc[2 * MAX_L];
int ap[MAX_L][2];
int str[MAX_L][25], Max[MAX_L][25];
int rmq[2 * MAX_L][25];

int raw[MAX_L][3], vine[MAX_L], v[MAX_L];

vector <int> a[MAX_L], c[MAX_L];

inline int cmp(int x, int y) {
	return raw[x][2] < raw[y][2];
}

int tata_comp(int nod) {
	if (vine[nod] != nod) {
		int v = tata_comp(vine[nod]);
		vine[nod] = v;
		return v;
	}
	else return nod;
}

void apm() {
	for (i = 1; i <= n; i++)
		vine[i] = i;
	vine[n + 1] = n + 1;
	sort(v + 1, v + m + 1, cmp);
	
	//parcurg muchiile si construiesc apm - ul
	for (i = 1; i <= m + n; i++) {
		//vad daca nodurile fac parte din aceeasi componenta
		if (tata_comp(raw[v[i]][0]) != tata_comp(raw[v[i]][1])) {
			if (raw[v[i]][2] == inf) raw[v[i]][2] = 0;
			a[raw[v[i]][0]].push_back(raw[v[i]][1]); c[raw[v[i]][0]].push_back(raw[v[i]][2]);
			a[raw[v[i]][1]].push_back(raw[v[i]][0]); c[raw[v[i]][1]].push_back(raw[v[i]][2]);
			
			//modific pozitia tatalui
			vine[tata_comp(raw[v[i]][0])] = tata_comp(raw[v[i]][1]);
		}
	}
}

void cit() {
	freopen("radiatie.in", "r", stdin);
	freopen("radiatie.out", "w", stdout);
	
	scanf("%d %d %d", &n, &m, &nr);
	
	for (i = 1; i <= m; v[i] = i, i++)
		scanf("%d %d %d", &raw[i][0], &raw[i][1], &raw[i][2]);
	for (i = 1; i <= n; v[i + m] = i + m, i++) {
		raw[m + i][0] = i;
		raw[m + i][1] = n + 1;
		raw[m + i][2] = inf;
	}
	
	apm();
}

void dfs(int w, int depth) {
	euler[++k] = w; adanc[k] = depth;
	nivel[w] = depth;
	
	int l = a[w].size();
	for (int i = 0; i < l; i++)
		if (fol[a[w][i]] == 0) {
			Max[a[w][i]][0] = c[w][i];
			fol[a[w][i]] = 1; tata[a[w][i]] = w;
			
			dfs(a[w][i], depth + 1);
			
			fol[a[w][i]] = 0;
			euler[++k] = w; adanc[k] = depth;
		}
}

void solve() {
	fol[n + 1] = 1; k = 0; 
	dfs(n + 1, 1);

	for (i = 1; i <= k; i++) {
		if (ap[euler[i]][0] == 0) ap[euler[i]][0] = i;
		ap[euler[i]][1] = i;
		rmq[i][0] = adanc[i];
	}
	
	for (j = 1; (1 << j) <= k; j++)
		for (i = 1; i <= k; i++) {
			rmq[i][j] = rmq[i][j - 1]; 
			if (i + (1 << (j - 1)) <= k && rmq[i][j] > rmq[i + (1 << (j - 1))][j - 1]) 
				rmq[i][j] = rmq[i + (1 << (j - 1))][j - 1]; 
		}
	
	//calculez al 1 << k - lea stramos al unui nod
	for (i = 1; i <= n; i++) str[i][0] = tata[i];
	for (j = 1; j <= 20; j++) {  
        for (i = 1; i <= n; i++)  
            str[i][j] = str[str[i][j - 1]][j - 1];
    }
	
	//calculez maximul pe intervalul i..i + 1<<k
	for (j = 1; (1 << j) <= n; j++) {
		for (i = 1; i <= n; i++) {
			Max[i][j] = Max[i][j - 1];
			if (nivel[i] - (1 << j) > 0) 
				Max[i][j] = max(Max[i][j - 1], Max[str[i][j - 1]][j - 1]);
		}
	}
}

int maxim(int nod, int niv) {
	int p2 = 20, curent = 0;
	int k = nivel[nod], x = nod;
	
	while (k > niv && p2) {
		while (k - (1 << p2) < niv && p2) p2--;
		curent = max(curent, Max[x][p2]);
		x = str[x][p2];
		k = nivel[x];
	}
	
	return curent;
}

void write() {

	for (i = 1; i <= nr; i++) {
		scanf("%d %d", &X, &Y);
		
		if (ap[X][0] < ap[Y][0]) p = ap[X][0];
		else p = ap[Y][0];
		if (ap[X][1] > ap[Y][1]) q = ap[X][1];
		else q = ap[Y][1];
		
		for (j = 0; j <= 20; j++)
			if (p + (1 << j) > q) break;
		j--;
		
		if (rmq[p][j] <= rmq[q - (1 << j)][j]) val = rmq[p][j];
		else val = rmq[q - (1 << j)][j];
		
		//lca -ul intre nodurile X si Y se va afla la adancimea val
		sol = max(maxim(X, val), maxim(Y, val));
		
		printf("%d\n",sol);
	}
}

int main() {

	cit();
	solve();
	write();
	
	return 0;
}