【洛谷P2245】星际导航

题面

题解

\(kruskal\)重构树板子题??(大雾

因为重构树上两点之间的\(LCA\)的权值就是原图上最小生成树上的瓶颈。

所以建个重构树,跑\(LCA\)即可。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);

inline int read()
{
	int data = 0, w = 1;
	char ch = getchar();
	while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int maxn(2e5 + 10), maxm(3e5 + 10);
struct edge { int next, to; } e[maxn << 2];
struct Edge { int from, to, dis; } E[maxm];

inline bool cmp(const Edge &lhs, const Edge &rhs) { return lhs.dis < rhs.dis; }
int fa[maxn], f[maxn], size[maxn], belong[maxn], heavy[maxn], head[maxn], e_num, cnt, pos[maxn], val[maxn], n, m, n_cnt;
inline void add_edge(int from, int to) { e[++e_num] = (edge) {head[from], to}; head[from] = e_num; }

void dfs(int x)
{
	size[x] = 1;
	for(RG int i = head[x]; i; i = e[i].next)
	{
		int to = e[i].to; if(to == fa[x]) continue;
		fa[to] = x; dfs(to); size[x] += size[to];
		if(size[heavy[x]] < size[to]) heavy[x] = to;
	}
}

void dfs(int x, int chain)
{
	pos[x] = ++cnt; belong[x] = chain;
	if(!heavy[x]) return;
	dfs(heavy[x], chain);
	for(RG int i = head[x]; i; i = e[i].next)
	{
		int to = e[i].to; if(to == fa[x] || to == heavy[x]) continue;
		dfs(to, to);
	}
}

inline int LCA(int a, int b)
{
	while(belong[a] != belong[b])
	{
		if(pos[belong[a]] < pos[belong[b]]) std::swap(a, b);
		a = fa[belong[a]];
	}
	return pos[a] < pos[b] ? a : b;
}

inline int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
inline void Kruskal()
{
	std::sort(E + 1, E + m + 1, cmp); n_cnt = n;
	for(RG int i = 1; i <= m; i++)
	{
		int fx = find(E[i].from), fy = find(E[i].to);
		if(fx == fy) continue;
		f[fx] = f[fy] = ++n_cnt; f[n_cnt] = n_cnt;
		add_edge(n_cnt, fx); add_edge(fx, n_cnt);
		add_edge(n_cnt, fy); add_edge(fy, n_cnt);
		val[n_cnt] = E[i].dis;
	}

	for(RG int i = n_cnt; i; i--)
		if(!pos[i]) dfs(i), dfs(i, i);
}

int main()
{
#ifndef ONLINE_JUDGE
	file(cpp);
#endif
	n = read(); m = read();
	for(RG int i = 1; i <= m; i++) E[i] = (Edge) {read(), read(), read()};
	for(RG int i = 1; i <= n; i++) f[i] = i;
	RG int q = read(); Kruskal();
	while(q--)
	{
		int a = read(), b = read();
		if(find(a) != find(b)) puts("impossible");
		else printf("%d\n", val[LCA(a, b)]);
	}
	return 0;
}
posted @ 2018-10-31 17:29  xgzc  阅读(208)  评论(0)    收藏  举报