Cod sursa(job #287454)

Utilizator rupraRupra C rupra Data 24 martie 2009 21:21:02
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.52 kb
#include <algorithm>
#include <stdio.h>
#include <vector>

#define pb push_back
#define mp make_pair
#define f first
#define s second
#define LIM 100000
#define MAX 20000

using namespace std;

vector <pair <int, int> > listDrum[MAX], fii[MAX];
pair <int, pair <int, int> > vctEdge[MAX * 2];
pair <short, int> stramos[MAX][15];
pair <short, short> nivele[LIM][18];
int n, m, testCases, nrViz;
int log2[LIM];
int poz[MAX], sel[MAX], tata[MAX];

inline int rad(int nod)
{
	if (tata[nod] == nod)
		return nod;

	tata[nod] = rad(tata[nod]);

	return tata[nod];
}

inline int constrArb(int nod)
{
	if (sel[nod])
		return 0;
	sel[nod] = 1;

	for (int i = 0; i < listDrum[nod].size(); i++)
		if (constrArb(listDrum[nod][i].f))
		{
			stramos[listDrum[nod][i].f][0] = mp(nod, listDrum[nod][i].s);

			fii[nod].pb(listDrum[nod][i]);
		}

	return 1;
}

inline void bRmqStramos(int nod)
{
	if (sel[nod])
		return;
	sel[nod] = 1;

	for (int alKlea = 1, ruda = stramos[nod][0].f; ruda; ruda = stramos[ruda][alKlea - 1].f, alKlea++)
		stramos[nod][alKlea] = mp(stramos[ruda][alKlea - 1].f, max(stramos[nod][alKlea - 1].s, stramos[ruda][alKlea - 1].s));

	for (int i = 0; i < fii[nod].size(); i++)
		bRmqStramos(fii[nod][i].f);
}

inline void parcurgereEulerArb(int nod, int depth)
{
	nivele[++nrViz][0] = mp(depth, nod);
	poz[nod] = nrViz;

	for (int i = 0; i < fii[nod].size(); i++)
	{
		parcurgereEulerArb(fii[nod][i].f, depth + 1);

		nivele[++nrViz][0] = mp(depth, nod);
	}
}

inline void bRmqLca()
{
	for (int lg = 0; lg <= log2[nrViz]; lg++)
	{
		int h = (1 << lg);

		for (int i = 1; i <= nrViz - h; i++)
			nivele[i][lg + 1] = (nivele[i][lg].f < nivele[i + h][lg].f)? nivele[i][lg] : nivele[i + h][lg];
	}
}

inline int aflaDist(int nod, int ad)
{
	int dist = 0;
	
	for (int lg = log2[ad] + 1, ruda = nod; ad && lg >= 0; lg--)
		if (ad >= (1 << lg))
		{
			dist = max(dist, stramos[ruda][lg].s);
			ruda = stramos[ruda][lg].f;
			ad -= (1 << lg);
		}

	return dist;
}

int main()
{
	freopen("radiatie.in", "r", stdin);
	freopen("radiatie.out", "w", stdout);

	for (int i = 2; i < LIM; i++)
		log2[i] = log2[i / 2] + 1;

	scanf("%d %d %d", &n, &m, &testCases);

	for (int i = 1; i <= m; i++)
		scanf("%d %d %d", &vctEdge[i].s.f, &vctEdge[i].s.s, &vctEdge[i].f);

	// Creez APM
	sort(vctEdge + 1, vctEdge + 1 + m);

	for (int i = 1; i <= n; i++)
		tata[i] = i;

	for (int i = 1; i <= m; i++)
		if (rad(vctEdge[i].s.f) != rad(vctEdge[i].s.s))
		{
			tata[rad(vctEdge[i].s.f)] = rad(vctEdge[i].s.s);

			listDrum[vctEdge[i].s.f].pb(mp(vctEdge[i].s.s, vctEdge[i].f));
			listDrum[vctEdge[i].s.s].pb(mp(vctEdge[i].s.f, vctEdge[i].f));
		}

	memset(sel, 0, sizeof(sel));
	constrArb(1);

	// Fac RMQ pe stramosi
	memset(sel, 0, sizeof(sel));
	bRmqStramos(1);

	// parcurgere Euler
	memset(sel, 0, sizeof(sel));
	parcurgereEulerArb(1, 1);

	// RMQ pentru LCA
	bRmqLca();

	// Acu raspund:)
	for (; testCases; testCases--)
	{
		int nod1, nod2;
		scanf("%d %d", &nod1, &nod2);

		int l1 = poz[nod1], l2 = poz[nod2];
		if (l1 > l2)
			swap(l1, l2), swap(nod1, nod2);
		int lung = l2 - l1;


		pair <short, short> maxDepth = (nivele[l1][log2[lung]].f < nivele[l2 - lung + 1][log2[lung]].f)? nivele[l1][log2[lung]] : nivele[l2 - lung + 1][log2[lung]];

		int maxGs = aflaDist(nod1, nivele[l1][0].f - maxDepth.f);
		maxGs = max(maxGs, aflaDist(nod2, nivele[l2][0].f - maxDepth.f));

		printf("%d\n", maxGs);
	}

	fclose(stdin);
	fclose(stdout);
	return 0;
}