A. Wormhole Sort 并查集 最小生成树

GDUT 2020寒假训练 排位赛三 A

原题链接

题目

A. Wormhole Sort 并查集 最小生成树

outputstandard output
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.

Input
The first line contains two integers, N and M.

The second line contains the N integers p1,p2,…,pN. It is guaranteed that p is a permutation of 1…N.
For each i between 1 and M, line i+2 contains the integers ai, bi, and wi.

Output
A single integer: the maximum minimal wormhole width which a cow must squish itself into during the sorting process. If the cows do not need any wormholes to sort themselves, output −1.

样例

input

4 4
3 2 1 4
1 2 9
1 3 7
2 3 10
2 4 3

output
9

题目大意

有n头奶牛在不同的位置上,我们要让这些奶牛交换位置,使其排列为1~ n的形式。现在有m个虫洞,联通了两个点,而这个中东有一定的宽度,通过虫洞可以交换两个位置的牛。现在我们要找到一个最大的宽度,让这些牛通过这个宽度以上的虫洞完成正确的排列

思路

首先,若a与b联通,b与c联通,则abc可以通过两两交换的形式使abc任意三点到达任意位置。那么在这道题中,若a与b在一个集合中,则a和b就能到达对方的位置。而我们要找的是一个最大宽度,使用这个宽度以上的虫洞可以完成互换任务。那么这个宽度以上的虫洞连接的点所形成的集合一定囊括了所有的应该进行交换的点。那么我们可以在读入的时候判断loc[i]是否与i相等,不相等则说明这头牛处于错误的位置。然后再读入虫洞,按照从大到小排序,然遍历虫洞,将虫洞连接的两端放入一个集合。在每一次合并完之后检查所有错误的位置所处的集合是否为同一集合,若已经统一了,则完成了交换的任务,那么当前虫洞的宽度就是所求的最大宽度。

这个过程挺像最小生成树的过程。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<memory.h>
using namespace std;
const int maxn=100007;
struct bian{
	int x,y;
	int w;
}b[maxn];
int loc[maxn];//牛的位置 
int w[maxn];
int n,m;
int wa=0;//错误的位置的牛的个数 
bool cmp(const bian &a,const bian &b)
{
	return a.w<b.w;
}
int fa[maxn];
int getfa(int x)
{
	return fa[x]==x? x:fa[x]=getfa(fa[x]);
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&loc[i]);
		if(loc[i]!=i)
		{
			wa++;
			w[wa]=i;
		}
		fa[i]=i;
	}
	if(wa==0)
	{
		cout<<-1<<endl;
		return 0;
	}
	
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].w);
	}
	sort(b+1,b+m+1,cmp);
	
	for(int i=m;i>=1;i--)
	{
		bool flag=true;
		int fx=getfa(b[i].x);
		int fy=getfa(b[i].y);
		fa[fx]=fy;
		for(int j=1;j<wa;j++)
		{
			if(getfa(w[j])!=getfa(w[j+1]))
			{
				flag=false;
				break;
			}
		}
		if(flag)
		{
			cout<<b[i].w<<endl;
			return 0;
		}
	}
	
	return 0;
}


上一篇:防晒


下一篇:Luogu P3052 [USACO12MAR]Cows in a Skyscraper G