Cod sursa(job #1312787)

Utilizator toranagahVlad Badelita toranagah Data 9 ianuarie 2015 22:21:43
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.93 kb
//Problem radiatie from Infoarena
#include <cassert>
#include <cmath>
#include <cstdint>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;
 
ifstream fin("radiatie.in");
ofstream fout("radiatie.out");

const int INF = 1 << 30;
const int MAX_N = 15100;
const int MAX_LOG = 15;

#define mp make_pair
typedef pair<int, int> pii;

int N, M, K;
vector<int> graph[MAX_N];
vector<pair<pii, int>> edges;

vector<pii> tree[MAX_N];
vector<pii> queries;

int depth[MAX_N];
int anc[MAX_LOG][MAX_N];
int mxCost[MAX_LOG][MAX_N];

void apm() {
	auto edgeComp = [](int e1, int e2) {
		return edges[e1].second > edges[e2].second;
	};

	priority_queue<int, vector<int>, decltype(edgeComp)> heap(edgeComp);
	vector<bool> visited(N + 1, false);
	vector<bool> inApm(M, false);

	auto get_free = [&visited](int e) {
		int a = edges[e].first.first, b = edges[e].first.second;
		return visited[a] ? b : a;
	};

	for (int i = 1, node = 1, next, edge; i < N; i += 1, node = next) {
		visited[node] = true;
		for_each(graph[node].begin(), graph[node].end(), [&heap](int e) {
			heap.push(e);
		});

		do {
			edge = heap.top();
			next = get_free(edge);
			heap.pop();
		} while (visited[next]);
		inApm[edge] = true;
	}

	for (int node = 1; node <= N; node += 1) {
		for (auto e: graph[node]) {
			if (inApm[e]) {
				int other = edges[e].first.first + edges[e].first.second - node;
				tree[node].push_back(mp(other, edges[e].second));
			}
		}
	}
}

void dfs(int node) {
	for (auto e: tree[node]) {
		if (depth[e.first] == 0) {
			depth[e.first] = depth[node] + 1;
			anc[0][e.first] = node;
			mxCost[0][e.first] = e.second;
			dfs(e.first);
		}
	}
}

void find_ancestors() {
	depth[1] = 1;
	dfs(1);

	for (int l = 1; l < MAX_LOG; l += 1) {
		for (int i = 1; i <= N; i += 1) {
			anc[l][i] = anc[l - 1][anc[l - 1][i]];
			mxCost[l][i] = max(mxCost[l - 1][i], mxCost[l - 1][anc[l - 1][i]]);
		}
	}
}

int nth_anc(int node, int n) {
	int result = 0;
	for (int bit = MAX_LOG - 1; bit >= 0; bit -= 1) {
		if (!((1 << bit) & n)) continue;
		if ((1 << bit) == n) {
			result = anc[bit][node];
		} else {
			node = anc[bit][node];
			n ^= (1 << bit);
		}
	}
	return result;
}

int lca(int a, int b) {
	if (a == b) return a;
	int da = depth[a], db = depth[b];
	if (da > db) {
		return lca(nth_anc(a, da - db), b);
	} else if (da < db) {
		return lca(a, nth_anc(b, db - da));
	} else {
		for (int bit = MAX_LOG - 1; bit >= 0; bit -= 1) {
			if (anc[bit][a] != anc[bit][b]) {
				a = anc[bit][a];
				b = anc[bit][b];
			}
		}
		return anc[0][a];
	}
}

int find_greatest(int a, int b) {
	if (a == b) return 0;
	int ancestor = lca(a, b);
	if (ancestor != a && ancestor != b) {
		return max(find_greatest(a, ancestor), find_greatest(b, ancestor));
	}
	if (ancestor == a) swap(a, b);

	int l = depth[a] - depth[ancestor];
	int result = -INF;
	for (int bit = MAX_LOG - 1; bit >= 0; bit -= 1) {
		if ((1 << bit) & l) {
			result = max(result, mxCost[bit][a]);
			a = anc[bit][a];
			l ^= (1 << bit);
		}
	}
	return result;
}


void readin() {
	fin >> N >> M >> K;
	edges.resize(M);
	for (int i = 0, a, b, c; i < M; i += 1) {
		fin >> a >> b >> c;
		edges[i] = mp(mp(a, b), c);
		graph[a].push_back(i);
		graph[b].push_back(i);
	}
	queries.resize(K);
	for (int i = 0, a, b; i < K; i += 1) {
		fin >> a >> b;
		queries[i] = mp(a, b);
	}
}

void solve() {
	apm();

#ifdef DEBUG
	for (int i = 1; i <= N; i += 1) {
		fout << i << ": ";
		for (auto j: tree[i]) {
			fout << j.first << "[" << j.second << "] ";
		}
		fout << endl;
	}
#endif
	find_ancestors();

#ifdef DEBUG
	for (int l = 0; l < 5; l += 1) {
		for (int i = 1; i <= N; i += 1) {
			fout << anc[l][i] << "[" << mxCost[l][i] << "] ";
		}
		fout << endl;
	}

	for (auto q: queries) {
		fout << "lca(" << q.first << ", " << q.second << ") = " << lca(q.first, q.second) << endl;
	}
#endif

	for (auto q: queries) {
		fout << find_greatest(q.first, q.second) << '\n';
	}
}


int main() {
	readin();
	solve();
	return 0;
}