首先,先明确题意:
以下情况不是树:
1.可以由不同路径到达一个结点的;
2.结点之间形成环的。eg 1 2 2 3 3 4 4 1 0 0
3.根结点不止一个的。
4.重复输入的。eg 1 2 1 2 0 0
5.0 0也是一棵树
以下情况不是树:
1.可以由不同路径到达一个结点的;
2.结点之间形成环的。eg 1 2 2 3 3 4 4 1 0 0
3.根结点不止一个的。
4.重复输入的。eg 1 2 1 2 0 0
5.0 0也是一棵树
好的,现在知道题意了,运用并查集的相关知识就可以解决了,详解见注释
#include <iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
int father[50000];
int re[50000];
int i,tree;
int find(int a){
int fa=father[a];
if(a!=father[a]){
father[a]=find(father[fa]); //注意递归的使用,表示我不会写递归啊有木有
return father[fa];
}
else return fa;
}
void link(int a,int b){
int x=find(a);
int y=find(b);
re[i++]=x; //记录下每次的根节点
if(y!=b||y==x){tree=0;return;}//如果y!=b说明之前b有不等于自己的父亲节点,所以现在b不止有一个父亲节点 y==x说明形成环
else father[b]=x;
}
int main()
{ int count=1;
int temp_x,temp_y;
while(scanf("%d %d",&temp_x,&temp_y))
{
if(temp_x+temp_y<0) break;
for(int k=0;k<50005;k++)
father[k]=k; //父亲结点初始化为自己
i=0;
int fa=temp_x;
int son=temp_y;
int ok=1;
tree=1;
while(1)
{ if(ok==0){scanf("%d %d",&fa,&son);}
if(fa+son==0){break;}
link(fa,son);
ok=0;
}
int root=find(re[0]);
for(int j=1;j<i;j++)
if(find(re[j])!=root) //查询之前记录的每个根节点的最终根结点是否为同一个,因为根结点在之后输入的数据中可能会更新
{ tree=0;break;}
if(tree==0)printf("Case %d is not a tree.\n",count++);
else printf("Case %d is a tree.\n",count++);
}
return 0;
}