Cod sursa(job #222946)

Utilizator plastikDan George Filimon plastik Data 26 noiembrie 2008 13:30:01
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.72 kb
#include <cstdio>

#include <map>
#include <vector>
#include <algorithm>
using namespace std;

#define cost first
#define son second
#define edge second

const int NMAX = 15005;
const int LOGMAX = 11;

multimap<int, pair<int, int> > Edges;
vector<pair<int, int> > Neighb[NMAX];
int Group[NMAX], n, m, k;

int Parent[NMAX][LOGMAX], Max[NMAX][LOGMAX];
int Depth[NMAX];
//int Start[NMAX], End[NMAX], Euler[NMAX], nEuler = 0;
//bool Used[NMAX];

void relabel(int bad, int good) {
	int i;
	for (i = 0; i < n; ++ i)
		if (Group[i] == bad)
			Group[i] = good;
}
void doKruskal() {
	int i;
	for (i = 0; i < n; ++ i)
		Group[i] = i;
	
	int nEdges;
	multimap<int, pair<int, int> >::iterator mi;
	for (mi = Edges.begin(), nEdges = 0; mi != Edges.end() && nEdges < n - 1; ++ mi)
		if (Group[mi->edge.first] != Group[mi->edge.second]) {
			relabel(Group[mi->edge.first], Group[mi->edge.second]);
			++ nEdges;
			Neighb[mi->edge.first].push_back(make_pair(mi->cost, mi->edge.second));
			Neighb[mi->edge.second].push_back(make_pair(mi->cost, mi->edge.first));
		}
}

void init() {
	int i, j;
	for (i = 0; i < n; ++ i)
		for (j = 0; (1 << j) <= n; ++ j) {
			Parent[i][j] = -1;
			Max[i][j] = 0;
		}
	Depth[0] = 1;
	for (i = 1; i < n; ++ i)
		Depth[i] = -1;
	
}

void doDepthFirst(int curr) {
	vector<pair<int, int> >::iterator vi;
	for (vi = Neighb[curr].begin(); vi != Neighb[curr].end(); ++ vi)
		if (Depth[vi->son] == -1) {
			Parent[vi->son][0] = curr;
			Max[vi->son][0] = vi->cost;
			//printf("%d ", Max[vi->son][0]);
			Depth[vi->son] = Depth[curr] + 1;
			doDepthFirst(vi->son);
		}
}

/*void doEulerTraversal(int curr) {
	Used[curr] = true;
	Start[curr] = End[curr] = nEuler;
	Euler[nEuler ++] = curr;
	
	vector<pair<int, int> >::iterator vi;
	for (vi = Neighb[curr].begin(); vi != Neighb[curr].end(); ++ vi)
		if (Used[vi->son] == false) {
			doEulerTraversal(vi->son);
			End[curr] = nEuler;
			Euler[nEuler ++] = curr;
		}
}*/

void getParents() {
	int i, j;
	for (j = 1; (1 << j) < n; ++ j)
		for (i = 0; i < n; ++ i)
			if (Parent[i][j - 1] != -1 && Parent[Parent[i][j - 1]][j - 1] != -1) {
				Parent[i][j] = Parent[Parent[i][j - 1]][j - 1];
				Max[i][j] = max(Max[i][j - 1], Max[Parent[i][j - 1]][j - 1]);
			}
}

int query(int a, int b) {
	int temp, ans = 0;
	//printf("%d %d\n", a, b);
	if (Depth[a] < Depth[b]) { // a e mai adanc in arbore si trebuie ridicat
		temp = a;
		a = b;
		b = temp;
	}
   //printf("%d %d\n\n", a,  b);
	
	int log; 
	for (log = 0; (1 << log) <= Depth[a]; ++ log); // determin log a.i. 2^log <= Depth[a] si log maxim
	-- log;
	
	int j; // am nevoie de stramosul Depth[a] - Depth[b] al lui a
	for (j = log; j >= 0; -- j)
		if (Depth[a] - (1 << j) >= Depth[b]) {
			ans = max(ans, Max[a][j]);
			a = Parent[a][j];
		}
	
	if (a == b)
		return ans;
	
	for (j = log; j >= 0; -- j)
		if (Parent[a][j] != -1 && Parent[a][j] == Parent[b][j]) { // stramosul comun e prea sus
			ans = max(ans, Max[a][j]); // daca urc nodurile, trec prin muchiile respective => update pentru raspuns
			ans = max(ans, Max[b][j]);
			
			a = Parent[a][j], b = Parent[b][j]; // urc cele 2 noduri si injumatatesc intervalul de cautare
		}
	ans = max(ans, Parent[a][0]);
	
	return ans;
}

int main() {
	
	freopen("radiatie.in", "r", stdin);
	freopen("radiatie.out", "w", stdout);
	
	scanf("%d %d %d", &n, &m, &k);
	int i, a, b, c;
	for (i = 0; i < m; ++ i) {
		scanf("%d %d %d", &a, &b, &c);
		 -- a, -- b;
		Edges.insert(make_pair(c, make_pair(a, b)));
	}
	
	doKruskal();
	init();
	doDepthFirst(0);
	getParents();
	
	for (i = 0; i < k; ++ i) {
		scanf("%d %d", &a, &b);
		-- a, -- b;
		printf("%d\n", query(a, b));
	}
	
	/*for (i = 0; i < n; ++ i)
		printf("%d ", Depth[i]);*/
	
	/*int j;
	for (i = 0; i < n; ++ i) {
		for (j = 0; j < 3; ++ j)
			printf("%d ", Max[i][j]);
		printf("\n");
	}*/
	
	return 0;
}