这是一棵树吗?
时间限制: 1 Sec
内存限制: 64 MB
题目描述
树是一种重要的数据结构。它要么为空,要么是一个或多个顶点的集合,这些顶点由有向边连结,并且具有如下性质: (1) 有且仅有1个结点,称为“根”。根结点没有边指向它; (2) 除根结点,每个结点仅有一条边指向它; (3) 从根到每个结点仅有一条唯一的路径。 例如,下面三个图中,第一、二个表示的是树,第三个不是。
给出顶点和有向边的信息,编一个程序判断这是一棵树吗?
输入
输入包含多组数据,每组数据格式为:多组空格分开的整数对,每个整数对j, k(1≤j, k≤10000) 表示一条有向边从结点j指向结点k。两个空格分开的0,表示一组数据的结束。 最后一组数据后的两个空格分开的-1,表示所有输入数据的结束
输出
每组测试数据单独输出一行,输出”Case k is a tree.” 或者 “Case k is not a tree.” ,这里的k表示测试数据的组号,从1开始计数。
样例输入
6 8 5 3 5 2 6 4
5 6 0 0
8 1 7 3 6 2 8 9 7 5
7 4 7 8 7 6 0 0
3 8 6 8 6 4
5 3 5 6 5 2 0 0
-1 -1
样例输出
Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.
提示
无
【初级*我的思路】
看到题目,我的初始想法就是按照题目的要求来做:首先,1) 有且仅有1个结点,称为“根”。根结点没有边指向它,那我们就可以判断有几个根,或是没有根。其次,2) 除根结点,每个结点仅有一条边指向它,可以判断每一个节点的所连边(用tot来储存),3) 从根到每个结点仅有一条唯一的路径(其实,我认为满足了第二个条件,是否第三个也满足了?【试试】)。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int cx[10005],father[10005],a,minl,maxj,roots,f;
int main()
{
int i,j;
while(1)
{
f=0;
minl=10005;maxj=-1;
memset(cx,0,sizeof(cx));
memset(father,0,sizeof(father));
while(1)
{
scanf("%d%d",&i,&j);
if(i==-1) return 0;
if(!i) break;
if(minl>i||minl>j) minl=min(i,j);
if(maxj<i||maxj<j) maxj=(i,j); //Hi
cx[i]=cx[j]=1;
father[j]++;
}
roots=0;
for(i=minl;i<=maxj;i++)
{
if(cx[i]&&father[i]==0)
{
roots++;
if(roots>1)
{
f=1;
break;
}
}
if(cx[i]&&father[i]>1)
{
f=1;
break;
}
}
if(!roots) f=1;
if(f) printf("Case %d is not a tree.\n",++a);
else printf("Case %d is a tree.\n",++a);
}
}
【改进】
遥看wrong红一片,仔细一看,才发现:原来我的max去哪了?又交,红得更惨了。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int cx[10005],father[10005],a,minl,maxj,roots,f;
int main()
{
int i,j;
while(1)
{
f=0;
minl=10005;maxj=-1;
memset(cx,0,sizeof(cx));
memset(father,0,sizeof(father));
while(1)
{
scanf("%d%d",&i,&j);
if(i==-1) return 0;
if(!i) break;
if(minl>i||minl>j) minl=min(i,j);
if(maxj<i||maxj<j) maxj=max(i,j);
cx[i]=cx[j]=1;
father[j]++;
}
roots=0;
for(i=minl;i<=maxj;i++)
{
if(cx[i]&&father[i]==0)
{
roots++;
if(roots>1)
{
f=1;
break;
}
}
if(cx[i]&&father[i]>1)
{
f=1;
break;
}
}
if(!roots) f=1;
if(f) printf("Case %d is not a tree.\n",++a);
else printf("Case %d is a tree.\n",++a);
}
}
【再改进】
妈啊,仔细想想,万一为空呢?它还是树吧。于是,我加上了……但没想到,我又wrong了。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int cx[10005],father[10005],a,minl,maxj,roots,f;
int main()
{
int i,j;
while(1)
{
f=0;
minl=10005;maxj=-1;
memset(cx,0,sizeof(cx));
memset(father,0,sizeof(father));
while(1)
{
scanf("%d%d",&i,&j);
if(i==-1) return 0;
if(!i) break;
if(minl>i||minl>j) minl=min(i,j);
if(maxj<i||maxj<j) maxj=max(i,j);
cx[i]=cx[j]=1;
father[j]++;
}
if(minl>maxj)
{
printf("Case %d is not a tree.\n",++a);
continue;
}
roots=0;
for(i=minl;i<=maxj;i++)
{
if(cx[i]&&father[i]==0)
{
roots++;
if(roots>1)
{
f=1;
break;
}
}
if(cx[i]&&father[i]>1)
{
f=1;
break;
}
}
if(!roots) f=1;
if(f) printf("Case %d is not a tree.\n",++a);
else printf("Case %d is a tree.\n",++a);
}
}
【终于明白,万物终和谐】
哎,还是自己的失误,写错了。
if(minl>maxj)
{
printf("Case %d is not a tree.\n",++a);
continue;
}
献上AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int cx[10005],father[10005],a,minl,maxj,roots,f;
int main()
{
int i,j;
while(1)
{
f=0;
minl=10005;maxj=-1;
memset(cx,0,sizeof(cx));
memset(father,0,sizeof(father));
while(1)
{
scanf("%d%d",&i,&j);
if(i==-1) return 0;
if(!i) break;
if(minl>i||minl>j) minl=min(i,j);
if(maxj<i||maxj<j) maxj=max(i,j);
cx[i]=cx[j]=1;
father[j]++;
}
if(minl>maxj)
{
printf("Case %d is a tree.\n",++a);
continue;
}
roots=0;
for(i=minl;i<=maxj;i++)
{
if(cx[i]&&father[i]==0)
{
roots++;
if(roots>1)
{
f=1;
break;
}
}
if(cx[i]&&father[i]>1)
{
f=1;
break;
}
}
if(!roots) f=1;
if(f) printf("Case %d is not a tree.\n",++a);
else printf("Case %d is a tree.\n",++a);
}
}