排位赛3-Wormhole Sort
题目
Farmer John’s cows have grown tired of his daily request that they sort themselves before leaving the barn each morning. They have just completed their PhDs in quantum physics, and are ready to speed things up a bit.
This morning, as usual, Farmer John’s N cows (1≤N≤105), conveniently numbered 1…N, are scattered throughout the barn at N distinct locations, also numbered 1…N, such that cow i is at location pi. But this morning there are also M wormholes (1≤M≤105), numbered 1…M, where wormhole i bidirectionally connects location ai with location bi, and has a width wi (1≤ai,bi≤N,ai≠bi,1≤wi≤109).
At any point in time, two cows located at opposite ends of a wormhole may choose to simultaneously swap places through the wormhole. The cows must perform such swaps until cow i is at location i for 1≤i≤N.
The cows are not eager to get squished by the wormholes. Help them maximize the width of the least wide wormhole which they must use to sort themselves. It is guaranteed that it is possible for the cows to sort themselves.
题意
n头奶牛的位置被打乱了,现在又m条通道,每条通道由ai到bi,宽度为wi,问将奶牛复位用到的通道的最小值的最大值是多少。
解法
怎么复位呢,其实把通道堪称一个个连通块每个连通块内的点可以自由交换,所以只要奶牛a目前所在的位置和原来的位置位于一个连通块内就可以回去,这里求最小值的最大值很容易想到二分答案,所以先将通道按宽度从大到小排,judge时,把宽度大于等于mid的通道加入,判断每头牛是否能复位即可。
代码:
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <math.h>
using namespace std;
struct CC
{
int x,y,w;
}r[100010];
int n,m,l,r1,s,a[100010],father[100010];
bool vis[100010];
bool rmp(CC x,CC y)
{
return x.w>y.w;
}
int getfather(int x)
{
if (father[x]==x) return father[x];
father[x]=getfather(father[x]);
return father[x];
}
bool judge(int x)
{
for (int i=1;i<=n;i++) father[i]=i;
for (int i=1;i<=m;i++)
{
if (r[i].w<x) break;
int fax=getfather(r[i].x);
int fay=getfather(r[i].y);
father[fax]=fay;
}
bool flag=true;
for (int i=1;i<=n;i++)
if (vis[i] || (getfather(a[i])==getfather(i))) continue; else flag=false;
return flag;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if (a[i]==i)
{
vis[i]=true;
s++;
}
}
for (int i=1;i<=m;i++) scanf("%d%d%d",&r[i].x,&r[i].y,&r[i].w);
sort(r+1,r+m+1,rmp);
l=r[m].w;r1=r[1].w;
if (s==n) printf("-1"); else
{
while (l+1<r1)
{
int mid=(l+r1)/2;
if (judge(mid)) l=mid; else r1=mid;
}
printf("%d",l);
}
return 0;
}