Cod sursa(job #219083)

Utilizator andrei-alphaAndrei-Bogdan Antonescu andrei-alpha Data 5 noiembrie 2008 09:42:35
Problema Radiatie Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.9 kb
using namespace std;

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>

#define pb push_back
#define f first
#define s second
#define sz size
#define II inline
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define mp make_pair

#define IN  "radiatie.in"
#define OUT "radiatie.out"
#define oo 1<<30
#define N_MAX 1<<14

typedef vector<int> VI;
vector< vector< pair<int,int> > > A1(N_MAX),A(N_MAX);
int rez,S[N_MAX],SM[N_MAX];
int lg[N_MAX],CS[N_MAX],poz[N_MAX],stv[N_MAX],hg[N_MAX],maxhg,tata[N_MAX];
int rmq[15][N_MAX],TA[15][N_MAX],drum[15][N_MAX];
bool viz[N_MAX];
int N,M,K;

priority_queue< pair<int,int> ,vector<pair<int,int> >, greater<pair<int,int> > > Q;

II void scan()
{
	int x,y,cc;
	freopen(IN,"r",stdin);
	freopen(OUT,"w",stdout);
	scanf("%d%d%d\n",&N,&M,&K);
	FOR(i,1,M)
	{
		scanf("%d%d%d\n",&x,&y,&cc);
		A1[x].pb( mp(y,cc) );
		A1[y].pb( mp(x,cc) );
	}	
	FOR(i,1,N)
		sort(A1[i].begin(),A1[i].end() );
}

II int find(int nod,int vecin)
{
	int l = A1[nod].sz() - 1;
	if(l < 0)
		return oo;
	int step,m;
	for(step = 1;step <= l;step <<= 1);
	for(m = 0;step;step >>= 1)
		if(m + step <= l && A1[nod][m+step-1].f < vecin)
			m += step;
	if(A1[nod][m].f == vecin)
		return A1[nod][m].s;
	else
		return oo;
}

II void make_tree()
{
	memset(viz,0,sizeof(viz));
	memset(S,1,sizeof(S));
	
	viz[1] = true;
	S[0] = oo;
	FOR(i,2,N)
	{
		S[i] = find(1,i);
		if(S[i] != oo)
		{
			SM[i] = 1;
			Q.push( mp(S[i],i) );
		}	
	}	
	
	for(;!Q.empty();)
	{
		int nod = Q.top().s;
		int dist = Q.top().f;
		
		Q.pop();
		if(viz[nod] || dist > S[nod])
			continue;
		
		viz[nod] = true;
		A[ SM[nod] ].pb( mp(nod,S[nod]) );
		A[ nod ].pb( mp(SM[nod],S[nod]) );
		
		int l = A1[nod].sz() - 1;
		FOR(i,0,l)
		{
			int next = A1[nod][i].f;
			if(!viz[next] && S[next] > find(nod,next) )
			{
				S[next] = find(nod,next);
				SM[next] = nod;
				Q.push( mp(S[next],next) );
			}
		}	
	}
/*FOR(i,1,N)
	{
		int l = A[i].sz() - 1;
		if(l < 0)
			continue;
		FOR(j,0,l)
			if(A[i][j].f < i)
				printf("%d %d\n",i,A[i][j].f);
	}
*/	
	vector< vector< pair<int,int> > >().swap(A1);
}


void euler(int nod, int niv)
{
	stv[ ++stv[0] ] = nod; 
	poz[nod] = stv[0];
	hg[nod] = niv;
	maxhg = max(maxhg,niv);
	
	int l = A[nod].sz()-1;
	FOR(i,0,l)
		if ( !poz[ A[nod][i].f ] ) 
		{
			tata[ A[nod][i].f ] = nod;
			CS[ A[nod][i].f ] = A[nod][i].s;
			euler( A[nod][i].f , niv + 1);
			stv[ ++stv[0] ] = nod; 
		}
}

void process()
{
	--lg[0];
	FOR(i,1,stv[0])
		lg[i] = lg[i>>1] + 1;
	
	FOR(i,1,stv[0])
		rmq[0][i] = stv[i];
		
	for(int i=1; (1<<i) <= stv[0];++i)
		for(int j=1;j+(1<<i)-1 <= stv[0];++j)
			if(hg[ rmq[i-1][j] ] < hg[ rmq[i-1][ j+(1<<i) - (1<<(i-1))] ])
				rmq[i][j] = rmq[i-1][j];
			else
				rmq[i][j] = rmq[i-1][j+(1<<i) - (1<<(i-1))];
	FOR(i,1,N)
		TA[0][i] = tata[i],
		drum[0][i] = CS[i];
		
	for(int i=1; (1<<i) <= maxhg;++i)
		for(int j=1; j <= N  ;++j)
		{
			if(hg[j] < 1<<i )
				continue;
			TA[i][j] = TA[i-1][ TA[i-1][j] ],
			drum[i][j] = max(drum[i-1][j],drum[i-1][ TA[i-1][j] ]);
		}	
}


inline int LCA(int nod1,int nod2)
{
	int x = poz[nod1],y = poz[nod2];
	if(x > y)
		swap(x,y);
	int log = lg[y-x+1];
	if(hg[ rmq[log][x] ] < hg[ rmq[log][ y-(1<<log) + 1 ] ])
		return rmq[log][x];
	else
		return rmq[log][ y-(1<<log) + 1 ];
}


void query(int x,int y)
{
	if(!x || !y)
		return;
	if(hg[y] < hg[x])
	{
		int log = lg[ hg[x]-hg[y] ];
		if(rez < drum[log][x] )
			rez = drum[log][x];
		query(TA[log][x],y);
	}	
}

  
void solve()
{
	int x,y;
	FOR(i,1,K)
	{
		scanf("%d%d\n",&x,&y);
		if(x == y)
		{	
			printf("0\n");
			continue;
		}
		rez = 0;
		int nod = LCA(x,y);
		query(x,nod);
		query(y,nod);
		printf("%d\n",rez);
	}	
}


int main()
{
	scan();
	make_tree();
	euler(1,0);
	process();
	solve();
	return 0;
}