关押罪犯

#include<bits/stdc++.h>
using namespace std;
int m,n,b[10000001],zz[10000001];

struct date {
	int x,y,z;
}a[10000001];
int find(int x)
{
	if(zz[x]==x)
	return x;
	zz[x]=find(zz[x]);
	return zz[x];
}
bool check(int a,int b)
{
a=find(zz[a]);
b=find(zz[b]);
	if(a==b)
	return 1;
	return 0;
}
bool ccc(date a,date b)
{
	return a.z>b.z;
}
void ad(int a,int b)
{
a=find(zz[a]);
b=find(zz[b]);
	zz[a]=b;
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	zz[i]=i;//为记录祖先做准备 
	for(int i=1;i<=m;i++)
	scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);//记录数据 
	sort(a+1,a+m+1,ccc);//将仇恨值进行比较排序
	for(int i=1;i<=m+1;i++)//为什么m+1呢?运行到m+1会输出0 
	{
		if(check(a[i].x,a[i].y))
		{
			printf("%d",a[i].z);
			break;
		}
		//因为已经排过序,先把最大的搞定。如果两个罪犯已经在同一监狱就输出,并退出;
		//为什么会已经在同一监狱呢?我们在后面的程序里为了避免更大的冲突将部分人已经硬性分到了不同监狱,
		//在有超过两个敌人的一个人经过排序后依然遍历到了第二个敌人的情况下,这两个敌人只能分到一个监狱,无法避免冲突。 
		else
		{
			if(b[a[i].x]==0)//从重到轻,只标记头号“敌人”,其他的只有靠边站
			b[a[i].x]=a[i].y;
			else
			ad(b[a[i].x],a[i].y);//将敌人的敌人合并,从此就有了共同祖先,必须在一个监狱,在一起了哈哈 
			if(b[a[i].y]==0)
			b[a[i].y]=a[i].x;//同上 
			else
			ad(b[a[i].y],a[i].x);
		}
	}
	return 0;
} 
考试时:当时拿到这道题完全是懵的。我可以用什么方法,这道题在考什么。
考试后:我的问题有两个。
1.没审出这道题是并查集。
2.即便审出因太久没做早就对于怎么编译忘得一干二净。
这道题的具体理解我已经写在的代码的注释里,接下来说一说我要注意的地方。
可以循环到m+1使其自动输出0。
关于并查集的函数我还很不熟练,自己编译后改了几次函数才改对。需要在近期多在洛谷上刷一些有关于并查集的题。

 

posted @ 2019-05-28 17:17  星星梦  阅读(149)  评论(0编辑  收藏  举报