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