ccf-201812-4

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

原题ccf官网还没放出,不过分数倒是出来了,有惊无险的100分通过了

凭着记忆的话大致是求一个连通图的生成树,且该生成树的最大的边要最小

众所周知,求生成树用并查集最快,遇到最大的最小或者最小的最大之类的字眼需要用到二分来解决

所以这题的解决办法就是——二分并查集

具体的细节看代码吧

#include<iostream>
using namespace std;
int f[500001];  //并查集数组 
int maxn=0,minn=9999999,m,n,r;
inline int findset(int x)  //并查集 
{
	if(x==f[x])
	return x;
	else
	return f[x]=findset(f[x]);
} 
struct edge{    //存边 
	int u,v,w;
}e[500001];

int main()
{
	cin>>n>>m>>r;  //n个点,m条边,根节点r 
	for(int i=0;i<m;++i)
	{
		cin>>e[i].u>>e[i].v>>e[i].w;
		maxn=max(maxn,e[i].w);  //降低二分时间 
		minn=min(minn,e[i].w);  //降低二分时间 
	}
	while(maxn>=minn+1)  //二分 
	{
		int mid=(maxn+minn)>>1,count=0;
		for(int i=1;i<=n;++i)  //初始化并查集数组,每次wwhile循环都需要进行一次 
		{
			f[i]=i;
		}
		for(int i=0;i<m;++i)
		{
			if(e[i].w>mid)
			continue;
			int x=findset(e[i].u),y=findset(e[i].v);
			if(f[x]!=y)
			{
				f[x]=y;
				count++;
			}
		} 
		if(count==n-1)  //可以生成树 
		{
			maxn=mid;
		}
		else
		{
			minn=mid+1;
		} 
	}
	cout<<maxn;
	return 0;
}
/*
4 
5 
1
1 2 501
1 3 501
2 4 1000
3 4 2
1 4 2
*/

猜你喜欢

转载自blog.csdn.net/imotolove/article/details/85111021