您的位置:首页 > 其它

poj1308 并查集

2015-09-08 21:27 267 查看
题意:和hdu1272差不多,只不过给出的是有向图,问图中的点是否是一颗树。

还是用并查集合并点,对于一条边,如果连接的两点已经在同一并查集内,则可以直接判否。合并时按边的方向记录点的入度,如果某个点入度大于1也就是某个点有多个父亲节点,则说明不是树。合并时顺便记录合并总次数,最后合并 点数-1 次则是树。

#include<stdio.h>
#include<string.h>

int fa[100005],num[100005];
bool vi[100005];

void init(){
for(int i=1;i<=100004;i++)fa[i]=i;
}

int find(int x){
int r=x,t;
while(r!=fa[r])r=fa[r];
while(x!=r){
t=fa[x];
fa[x]=r;
x=t;
}
return r;
}

int main(){
int a,b,c=0;
while(scanf("%d%d",&a,&b)!=EOF&&a!=-1||b!=-1){
printf("Case %d is ",++c);
if(a==0&&b==0){printf("a tree.\n");continue;}
init();
memset(num,0,sizeof(num));
memset(vi,0,sizeof(vi));
bool f=1;
int x=find(a),y=find(b),cnt=0,ans=0;
if(!vi[a]){
cnt++;
vi[a]=1;
}
if(!vi[b]){
cnt++;
vi[b]=1;
}
num[b]++;
if(num[b]>1)f=0;
if(x!=y){
fa[x]=y;
ans++;
}
else f=0;
while(scanf("%d%d",&a,&b)&&a!=0||b!=0){
x=find(a),y=find(b);
if(!vi[a]){
cnt++;
vi[a]=1;
}
if(!vi[b]){
cnt++;
vi[b]=1;
}
num[b]++;
if(num[b]>1)f=0;
if(x!=y){
fa[x]=y;
ans++;
}
else f=0;
}
if(ans==cnt-1&&f)printf("a tree.\n");
else printf("not a tree.\n");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: