这道题坑了我好久啊!!!!!必须写下来;
首先必须的清楚如何判断是不是一颗树就本题而言:(1)整个图中只能有一个根节点,如果根节点的个数大于1个,那么就不是树了,而是森林。
(2)不能成环,也就是说两个点之间只能有一条路径到达,这里可以用并查集中的并操作进行判断
(3)如果a->b,必须判断b是不是根节点,加入b不是根节点,就不能让a->b;
另外要注意的一个地方就是:结束条件
如果你写成:if (x==-1&&y==-1)break;
那么就会RE
应该改为: if(x<0&&y<0)break;
附上代码:
#include <iostream>
#include <stdio.h>
using namespace std;
int f[100100],visit[100100],flag; //f[]数组存i节点的父节点,visit[]数组记录某个点是否被访问
int find(int x) //查操作,找到每个节点的祖先节点
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
void make(int a,int b) //并操作
{
int f1=find(a);
int f2=find(b);
if(f1==f2) //如果两者相等,说明成环,让flag=0
flag=0;
if(f2!=b) //如果不等 ,说明b不是根结点,入读不为1,那么就不能再让a指向b
flag=0;
else
f[f2]=f1;
}
int main()
{
int a,b,max=0,test=1;
while(cin>>a>>b)
{
if(a<0&&b<0)break;
if(a==0&&b==0)
{
printf("Case %d is a tree.\n",test++);
continue;
}
for(int i=1;i<=100010;i++) //初始化
{
f[i]=i;
visit[i]=0;
}
flag=1;
max=0;
visit[a]=visit[b]=1;
if(a>max)max=a; //max 存节点编号的最大值
if(b>max)max=b;
make(a,b);
while(cin>>a>>b)
{
if(a==0&&b==0)break;
visit[a]=visit[b]=1;
if(a>max)max=a;
if(b>max)max=b;
make(a,b);
}
if(!flag)
{
printf("Case %d is not a tree.\n",test++);
continue;
}
int k=0;
for(int i=1;i<=max;i++)
{
if(visit[i]&&f[i]==i) //这是要找出这课书中根节点的数目
k++;
if(k>1)break;
}
if(k>1)
printf("Case %d is not a tree.\n",test++);
else
printf("Case %d is a tree.\n",test++);
}
return 0;
}