题解 P2307 【迷宫】
并查集
这道题简化来说可以这样翻译(每组数据):
每次输入两个元素:a,b
如果这两个元素在一个集合内,那么对于这组数据,输出0,进入下一组数据
如果不在一个集合内,则合并这两个集合
最后如果只有1个集合输出1,否则输出0
那么这样就很好弄了,code:
#include <cstdio>
#include <cstring>
int f[100001]/*祖先*/,a,b,sum/*集合数量*/;
bool book[100001]/*是否出现*/,flag/*是否违规*/;
void cls(){//初始化
for(register int i=1;i<=100000;i++) f[i]=i;
memset(book,0,sizeof(book));sum=0;flag=false;
}
int find(int x){//路径压缩般找祖先
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
int main(){
cls();
while(scanf("%d%d",&a,&b)==2)//疯狂输入
{
if(a==-1&&b==-1) break;
if(a==0&&b==0) {printf("%c\n",((!flag&&sum==1)?'1':'0'));cls();continue;}//这组数据结束
if(!book[a]) sum++;//集合增加
if(!book[b]) sum++;//集合增加
book[a]=true;book[b]=true;//标记
int x1=find(a),x2=find(b);//祖先
if(x1==x2) flag=true;//标记
else {sum--;f[x1]=x2;}//修改
}
return 0;
}
我觉得这道题可以拓展成最小生成树算法中的Kruskal的一个主要的片段
有兴趣的可以查一下