题目链接:POJ1308
数据加强版HDU1325
注意几个特殊的点 来自discuss@xuhanqiu
1: 0 0 空树是一棵树 2: 1 1 0 0 不是树 不能自己指向自己 3: 1 2 1 2 0 0 不是树....自己开始一直在这么WA 好郁闷 重复都不行呀~~5555 4: 1 2 2 3 4 5 不是树 森林不算是树(主要是注意自己) 5: 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 1 注意 一个节点在指向自己的父亲或祖先 都是错误的 即 9-->1 错 6: 1 2 2 1 0 0 也是错误的AC代码:
/*
2017年8月28日11:41:56
POJ1308 数据加强版HDU1325
这个可以过 HDU1325
并查集入门,判定是不是树
AC
*/
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
const int maxn=1e5+10;
int pre[maxn];
int root[maxn];
bool circle,f;
void init(){
for(int i=1;i<=maxn;i++){
pre[i]=i;
root[i]=0;
}
circle=false;
f=false;
}
int find(int x){
int r=x;
while(pre[r]!=r) r=pre[r];//查找到根节点为止
int i=x,j;
while(i!=r){
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y){
if(x==y) circle=true;//自己不能指向自己
int fx=find(x);
int fy=find(y);
if(fx==fy||fy!=y){//一个子节点只能有一个父亲
circle=true;
}
else if(fx!=fy) pre[fy]=fx; //子节点链到父节点上
//else circle=true; 判断环
}
int main(){
int kase=0;
while(true){
init();
int a,b;
scanf("%d%d",&a,&b);//empty tree
if(a<0&&b<0) break;
else if(a==0||b==0){
printf("Case %d is a tree.\n",++kase);
continue;
}
join(a,b);
while(true){
scanf("%d%d",&a,&b);
if(a==0&&b==0) break;
join(a,b);
}
for(int i=1;i<=maxn;i++){
if(find(i)!=i){
root[find(i)]++;
// printf("root[%d]=%d\n",find(i),root[find(i)]);
}
}
int rt=0;
for(int i=1;i<=maxn;i++){
if(root[i]>0) rt++;
}
if(rt>1) circle=true;
//printf("rt=%d\n",rt);
if(!circle)
printf("Case %d is a tree.\n",++kase);
else
printf("Case %d is not a tree.\n",++kase);
}
return 0;
}