uva11354 找瓶颈路径——并查集按秩合并

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zz_ylolita/article/details/82821709

在做最小生成树的时候,使用并查集的按秩合并,不会破坏树的结构,复杂度O(logn)

#include <bits/stdc++.h>
using namespace std;
#define INF 1000000009
#define N 50010
int n,m,q,x,y;
int fa[N],Rank[N],edge[N],c[N];
struct node
{
	int x,y,z;
}a[100010];
int cmp(node a, node b)
{
	return a.z < b.z;
}
int Find(int x)
{
	return fa[x] == x ? x:Find(fa[x]);
}
void Kruscal()
{
	int s = 0,f1,f2;
	for (int i=1;i<=n;i++) fa[i] = i, Rank[i] = 1;
	memset(edge, 0, sizeof(edge));
	for (int i=1;i<=m;i++)
	{
		f1 = Find(a[i].x);
		f2 = Find(a[i].y);
		if (f1 != f2)
		{
			if (Rank[f1] < Rank[f2])
			{
				fa[f1] = f2;
				edge[f1] = a[i].z;
				Rank[f2] = max(Rank[f2], Rank[f1]+1);
			}
			else 
			{
				fa[f2] = f1;
				edge[f2] = a[i].z;
				Rank[f1] = max(Rank[f1], Rank[f2]+1);
			}
			s++;
		}
		if (s == n-1) break;
	}
}
int query(int x, int y)
{
	for (int i=1;i<=n;i++) c[i] = -1;//表示从x往上走走到i的时候路径的最大值
	int tmp = 0, ans = 0;
	while (1)
	{
		c[x] = tmp;
		if (fa[x] == x) break;
		tmp = max(tmp, edge[x]);
		x = fa[x];
	}
	while (1)
	{
		if (c[y] >= 0){ans = max(ans,c[y]);break;}//走到了x和y的LCA的位置了
		if (fa[y] == y) break;
		ans = max(ans, edge[y]);
		y = fa[y];

	}
	return ans;
}
int main()
{
	bool flag = 0;
	while (~scanf("%d%d", &n, &m))
	{
		if (flag) printf("\n");
		for (int i=1;i<=m;i++)
			scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
		sort(a+1,a+m+1,cmp);
		Kruscal();
		scanf("%d", &q);
		for (int i=1;i<=q;i++)
		{
			scanf("%d%d", &x, &y);
			printf("%d\n", query(x,y));
		}
		flag = 1;
	}
}

猜你喜欢

转载自blog.csdn.net/zz_ylolita/article/details/82821709