Cod sursa(job #2524950)

Utilizator borcanirobertBorcani Robert borcanirobert Data 16 ianuarie 2020 17:14:27
Problema Radiatie Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.86 kb
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

ifstream fin("radiatie.in");
ofstream fout("radiatie.out");

struct Edge{
	int x, y, cost;
	
	bool operator < (const Edge& other) const
	{
		return cost < other.cost;
	}
};

using VI  = vector<int>;
using VVI = vector<VI>;
using VB  = vector<bool>;
using PII = pair<int, int>;
using VP  = vector<PII>;
using VVP = vector<VP>;

int N, M, K;
VVP G;
VI f, w;
vector<Edge> edges;
VI h, t;				// Union-find
VVI dp, c;
VI lv;
int lvmax, lg;

void ReadData();
void Solve();
void Kruskal();
void DFS(int node, int p);
void Union(int x, int y);
int Find(int x);
void Precalc();
int Query(int x, int y);

int main()
{
	ReadData();
	Solve();
	
	fin.close();
	fout.close();
	return 0;
}

void ReadData()
{
	fin >> N >> M >> K;
	
	edges = vector<Edge>(M);
	G = VVP(N + 1);
	
	for (int i = 0; i < M; ++i)
		fin >> edges[i].x >> edges[i].y >> edges[i].cost;
}

void Solve()
{
	Kruskal();
	Precalc();
	
	int x, y;
	while (K--)
	{
		fin >> x >> y;
		
		fout << Query(x, y) << '\n';
	}
}

void Kruskal()
{
	h = t = VI(N + 1);
	for (int i = 1; i <= N; ++i)
		t[i] = i;
	
	sort(edges.begin(), edges.end());
	int cnt{0};
	for (const Edge& e : edges)
	{
		int x = e.x;
		int y = e.y;
		int c = e.cost;
		
		int c1 = Find(x);
		int c2 = Find(y);
		
		if (c1 == c2)
			continue;
		
		G[x].emplace_back(y, c);
		G[y].emplace_back(x, c);
		Union(c1, c2);
		
		++cnt;
		if (cnt == N - 1)
			break;
	}
}

void DFS(int node, int p)
{
	f[node] = p;
	lv[node] = lv[p] + 1;
	lvmax = max(lvmax, lv[node]);
	for (const auto& v : G[node])
	{
		if (v.first == p)
			continue;
		
		w[v.first] = v.second;
		DFS(v.first, node);
	}
}

void Union(int x, int y)
{
	if (h[x] < h[y])
		t[x] = y;
	else
	{
		t[y] = x;
		
		if (h[x] == h[y])
			++h[x];
	}
}

int Find(int x)
{
	if (x == t[x])
		return x;
	return t[x] = Find(t[x]);
}

void Precalc()
{
	f = w = VI(N + 1);
	lv = VI(N + 1);
	DFS(1, 0);
	
//	for (int i = 1; i <= N; ++i)
//		cout << i << ' ' << f[i] << '\n';

	lg = 0;
	while ((1 << lg) <= lvmax)
		++lg;
	
	dp = c = VVI(lg + 1, VI(N + 1));
	dp[0][1] = c[0][1] = 0;
	
	for (int i = 2; i <= N; ++i)
	{
		dp[0][i] = f[i];
		c[0][i] = w[i];
		
		//cout << i << ' ' << w[i] << '\n';
	}
	
	for (int k = 1; k <= lg; ++k)
		for (int i = 1; i <= N; ++i)
		{
			dp[k][i] = dp[k - 1][dp[k - 1][i]];
			c[k][i] = max(c[k - 1][i], c[k - 1][dp[k - 1][i]]);
		}
}

int Query(int x, int y)
{
	if (lv[x] > lv[y])
		return Query(y, x);
	
	int ans{0};
	int t = lg;
	while (t >= 0 && lv[x] != lv[y])
	{
		if (lv[dp[t][y]] >= lv[x])
		{
			ans = max(ans, c[t][y]);
			y = dp[t][y];
		}
		
		--t;
	}
	
	//cout << ans << ' ' << x << ' ' << y << '\n';
	
	t = lg;
	while (t >= 0 && x != y)
	{
		if (dp[t][x] != dp[t][y])
		{
			ans = max(ans, max(c[t][x], c[t][y]));
			x = dp[t][x];
			y = dp[t][y];
		}
		
		--t;
	}
	
	if (x != y)
		ans = max(ans, max(w[x], w[y]));
	
	return ans;
}