题目链接:
POJ 1308 Is It A Tree?
题意:
给出若干点对a, b,表示a指向b,以0 0结尾。判断这些点对能否组成一颗树。
分析:
①:空树是一棵树
②:点对中不能出现自己指向自己,这时不是一棵树
③:不能对于每一个点最多只有一个点指向它,而一个点可以指向多个点,这里可以用并查集判断。
主要是考虑a->b是否有b->a的情况。
④:是否是森林,也就是有多个根节点。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=100010;
int vis[maxn],cases,u,v,pre[maxn],maxnum;
int find(int x)
{
return pre[x]==x?x:pre[x]=find(pre[x]);
}
void mix(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
pre[fy]=fx;//从x指向y相当于x是y的祖先
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
cases=0;
while(~scanf("%d%d",&u,&v))
{
if(u==-1&&v==-1) break;
if(u==0&&v==0)//空树
{
printf("Case %d is a tree.\n",++cases);
continue;
}
memset(vis,0,sizeof(vis));
for(int i=0;i<maxn;i++) pre[i]=i;
maxnum=-1;
maxnum=max(maxnum,u);
maxnum=max(maxnum,v);
mix(u,v);
int flag=0;//flag=1:不是树
if(u==v) flag=1;//自己不能指向自己
while(1)
{
scanf("%d%d",&u,&v);
if(u==0&&v==0) break;
vis[u]=vis[v]=1;
maxnum=max(maxnum,u);
maxnum=max(maxnum,v);
if(u==v) flag=1;
if(flag) continue;
if(find(u)==find(v)) flag=1;
mix(u,v);
}
if(flag)//含有环
{
printf("Case %d is not a tree.\n",++cases);
continue;
}
else //判断是否是森林
{
flag=0;
int first=1;
int com=-1;
for(int i=1;i<=maxnum;i++)
{
if(vis[i])
{
if(first)
{
first=0;
com=find(i);
}
else
{
if(com!=find(i)) flag=1;
}
if(flag) break;//是森林
}
}
if(flag) printf("Case %d is not a tree.\n",++cases);
else printf("Case %d is a tree.\n",++cases);
}
}
return 0;
}