NOIP2010 提高组 复赛 prison 关押罪犯
//P1525 关押罪犯
//代码角度来说,这篇文章写得比较漂亮http://hzwer.com/599.html
//该题用并查集的核心是,敌人的敌人是朋友。
//e[i].a+n表示e[i].a的对立面,属不同的两个集合,而该问题中一共两个集合。
//f[e[i].a+n] 与 f[e[i].a]爸爸不同。
//看懂他人代码比较关键的一条是:带入输入数据进行手动模拟。该题收获之一。
//该题收获之二,集合合并原来可以写得这么简洁。
#include <stdio.h>
#include <string.h>
int f[20000*2+100];
struct node{
int a,b,c;
}e[100000+100],e_t;
void quicksort(int left,int right){//快排,从大到小
int i=left,j=right,mid=e[(left+right)/2].c;
while(i<=j){
while(e[i].c>mid)
i++;
while(e[j].c<mid)
j--;
if(i<=j){
e_t=e[i];
e[i]=e[j];
e[j]=e_t;
i++;
j--;
}
}
if(left<j)
quicksort(left,j);
if(i<right)
quicksort(i,right);
}
int getf(int u){//找爸爸
if(f[u]==u)
return f[u];
f[u]=getf(f[u]);
return f[u];
}
int main(){
int n,m,i,j,f1,f2;
scanf("%d%d",&n,&m);
for(i=1;i<=2*n;i++)
f[i]=i;
for(i=1;i<=m;i++)
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
quicksort(1,m);
for(i=1;i<=m;i++){
f1=getf(e[i].a);
f2=getf(e[i].b);
if(f1==f2){
printf("%d\n",e[i].c);
return 0;
}
f[f2]=getf(e[i].a+n);//合并集合 ,敌人的敌人是朋友
f[f1]=getf(e[i].b+n);
}
printf("0\n");
return 0;
}
本文针对NOIP2010提高组复赛中的“监狱问题”进行了详细解析,介绍了如何利用并查集解决该问题,并通过具体代码实现了快速排序、查找集合根节点及合并集合等功能。

841

被折叠的 条评论
为什么被折叠?



