【八中*二叉树】这是一棵树吗?

这是一棵树吗?

时间限制: 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);   
    }   
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值