其他分享
首页 > 其他分享> > 20.2.25排位赛A

20.2.25排位赛A

作者:互联网

【题目大意】
有n(1<=n<=10^5)只编号为1,2,3…,n的奶牛分别位于p1,p2,p3,…,pn(1<=pi<=n)的位置上,有m(1<=m<=10 ^5)条虫洞,第i条虫洞连接着ai与bi,它的宽度为wi。(1<=ai,bi<=n,ai≠bi,1<=wi<=10 ^ 9).在任意时刻,位于虫洞两端的奶牛可以交换位置。奶牛想通过虫洞使得编号为i的奶牛位于位置i上(1<=i<=n)。奶牛想让它们必须使用的虫洞中的最小值越大越好,求这个值最大是多少,如果不存在输出-1.
【解题思路】
题目的意思大概是这样:选取若干条边,对于任意不在位置i上的奶牛i,通过连边能够使得位置i与位置pi有路径,要求边的最小值越大越好。判断位置i与位置pi是否有路径可用并查集进行判断。将边按宽度大到小排好。题目就转换成选取前x条边。显然可以用二分答案二分边的数量。
【代码】

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
struct data
{
	int x,y,w;
}a[101010];
int fa[101010];
bool c[101010];
bool sym[101010];
int b[101010];
int n,m,s,ans,num;
bool symt;
bool cmp(data x,data y)
{
	return (x.w>y.w);
}
int get_father(int x)
{
	if (fa[x]==x) return x;
	fa[x]=get_father(fa[x]);
	return fa[x];
}
void Get_fa(int mid)
{
	int st,ed=mid;
	if (mid>=s) st=s+1;
	else 
	{
	  for (int i=1;i<=s;i++)
	    fa[i]=i;
	  st=1;
    }
	for (int i=st;i<=ed;i++)
	  {
		int xx=get_father(a[i].x);
	  	int yy=get_father(a[i].y);
	  	if (xx==yy) continue;
	  	fa[xx]=yy;
	  }
	s=mid;  
}
bool check()
{
	int t=-1;
	for (int i=1;i<=n;i++)
	  {
	    if (b[i]!=i)
		{
			int xx=get_father(i);
			int yy=get_father(b[i]);
			if (xx!=yy) return false;
		}
	  }
	return true;  
		
}
void work()
{
	int l=1,r=m;
     
	for (int i=1;i<=n;i++) fa[i]=i; 
	while (l<=r)
	{
		int mid=(l+r)/2;
		Get_fa(mid);
		if (check()) 
		{
			ans=a[mid].w;
			r=mid-1;
		}else l=mid+1;
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	int num=0;
	bool tt=true;
	for (int i=1;i<=n;i++)
	  {
	  	scanf("%d",&b[i]);
	    if (b[i]!=i) tt=false;
	  }
	for (int i=1;i<=m;i++)
	  scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);    
    sort(a+1,a+m+1,cmp); 
	if (tt) ans=-1;
	else work(); 
    printf("%d",ans);
	return 0;  
	 
}
水墨青杉 发布了59 篇原创文章 · 获赞 0 · 访问量 1368 私信 关注

标签:25,20.2,int,排位赛,mid,fa,bool,include,101010
来源: https://blog.csdn.net/weixin_45723759/article/details/104522212