Cod sursa(job #253497)

Utilizator tvladTataranu Vlad tvlad Data 5 februarie 2009 21:00:21
Problema Radiatie Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.89 kb
#include <cstdio>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

const int N_MAX = 15000;
const int logN = 15;
const int aIntSize = 1 << logN;
const int INF = 0x3f3f3f3f;

int n,m,k;
vector< pair<int,int> > G[N_MAX];
vector< pair<int,int> > APM[N_MAX];
typedef vector< pair<int,int> >::iterator EdgeIt;

int aInt[aIntSize+1];
int level[N_MAX];
int str[N_MAX][logN];
int mmax[N_MAX][logN];
vector<int> stack;

void aint_insert ( int cur, int st, int en, int x, int w ) {
	if (st == x && x == en) {
		aInt[cur] = w;
		return;
	}
	int m = st + (en-st)/2;
	if (x <= m) aint_insert(cur*2,st,m,x,w);
	if (x > m) aint_insert(cur*2+1,m+1,en,x,w);
	aInt[cur] = max(aInt[cur*2],aInt[cur*2+1]);
}

int aint_query ( int cur, int st, int en, int ist, int ien ) {
	if (ist <= st && en <= ien)
		return aInt[cur];
	int m = st + (en-st)/2;
	int r1 = -INF, r2 = -INF;
	if (ist <= m) r1 = aint_query(cur*2,st,m,ist,ien);
	if (ien > m) r2 = aint_query(cur*2+1,m+1,en,ist,ien);
	return max(r1,r2);
}

void df ( int k, int in_weight ) {
	level[k] = stack.size();
	stack.push_back(k);
	if (k) aint_insert(1,1,n,level[k],in_weight);
	for (int i = 0; (1 << i) <= level[k]; ++i) {
		str[k][i] = stack[level[k] - (1 << i)];
		mmax[k][i] = aint_query(1,1,n,level[k] - (1 << i) + 1, level[k]);
	}
	for (EdgeIt i = APM[k].begin(); i != APM[k].end(); ++i) {
		if (level[i->first] == -1) {
			df(i->first,i->second);
		}
	}
	stack.pop_back();
}

void precalc() {
	for (int i = 0; i < n; ++i) level[i] = -1;
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < logN; ++j)
			mmax[i][j] = -INF;
	for (int i = 0; i <= aIntSize; ++i) aInt[i] = -INF;
	df(0,-1);
}

int trace ( int &nod, int d ) {
	int m = -INF;
	for (int i = 0; (1 << i) <= d; ++i) {
		if ((1 << i) & d) {
			m = max(m,mmax[nod][i]);
			d -= (1 << i);
			nod = str[nod][i];
		}
	}
	return m;
}

int solve ( int x, int y ) {
	if (x == y) return 0;
	if (level[x] > level[y]) x ^= y ^= x ^= y;
	int m = trace(y,level[y]-level[x]), lvl = level[x];
	int step;
	for (step = 1; (1 << (step + 1)) <= lvl; ++step);
	for (; step >= 0; --step) {
		if (str[x][step] != str[y][step]) {
			m = max(m,mmax[x][step]);
			x = str[x][step];
			m = max(m,mmax[y][step]);
			y = str[y][step];
		}
	}
	if (x != y) {
		m = max(m,mmax[x][0]);
		m = max(m,mmax[y][0]);
		x = str[x][0];
		y = str[y][0];
	}
	return m;
}

int dist[N_MAX];
class dcmp {
public:
	bool operator() ( const int &a, const int &b ) { return dist[a] < dist[b]; };
};

struct FullEdge {
	int a,b,v;
};
void get_apm ( vector< pair<int,int> > G[], int n, vector< pair<int,int> > A[] ) {
	set<int,dcmp> S;
	vector<FullEdge> vei(n);
	vector<bool> used(n);
	set<int,dcmp>::iterator cur = S.begin();
	dist[0] = 0;
	used[0] = true;
	for (int i = 1; i < n; ++i) dist[i] = 0x3f3f3f3f;
	for (S.insert(0); !S.empty(); ) {
		cur = S.begin();
		if (*cur != 0) {
			used[*cur] = true;
			A[vei[*cur].a].push_back(make_pair(vei[*cur].b, vei[*cur].v));
			A[vei[*cur].b].push_back(make_pair(vei[*cur].a, vei[*cur].v));
		}
		for (EdgeIt i = G[*cur].begin(); i != G[*cur].end(); ++i) {
			if (dist[i->first] > i->second && !used[i->first]) {
				set<int,dcmp>::iterator loc = S.find(i->first);
				if (loc != S.end())
					S.erase(loc);
				dist[i->first] = i->second;
				vei[i->first].a = *cur;
				vei[i->first].b = i->first;
				vei[i->first].v = i->second;
				S.insert(i->first);
			}
		}
		S.erase(cur);
	}
}

int main() {
	freopen("radiatie.in","rt",stdin);
	freopen("radiatie.out","wt",stdout);
	scanf("%d %d %d",&n,&m,&k);
	for (int i = 0, a,b,v; i < m; ++i) {
		scanf("%d %d %d",&a,&b,&v);
		--a; --b;
		G[a].push_back(make_pair(b,v));
		G[b].push_back(make_pair(a,v));
	}

	get_apm(G,n,APM);
	precalc();
	for (int i = 0, a,b; i < k; ++i) {
		scanf("%d %d",&a,&b);
		--a; --b;
		printf("%d\n",solve(a,b));
	}
	return 0;
}