(1374): 这是一棵树吗?

本文介绍了一个用于判断给定数据是否构成树形结构的算法。通过分析顶点与有向边的关系,确保数据满足树的定义:单一根节点、每个节点只有一个父节点及从根到每个节点的唯一路径。

时间限制: 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开始计数。

样例输入

Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

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

样例输出

<span id="sample_output" style="color:#333333">Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.</span>

 

 

反正我就在想,不是一棵树的,要么有N多个根,要么没根,要么一个节点有N多个爸爸~

于是乎,第一份代码就出炉了...

#include<cstdio>
#include<cstring>
int apprd[10005],soned[10005],a,minx,maxx,roots,failed;
int main()
{
    int i,j;
    while(1)
    {
        failed=0;
        minx=10005;maxx=0;
        memset(apprd,0,sizeof(apprd));
        memset(soned,0,sizeof(soned));
        while(1)
        {
            scanf("%d%d",&i,&j);
            if(i==-1) return 0;
            if(!i) break;
            if(minx>i) minx=i;
            if(minx>j) minx=j;
            if(maxx<i) maxx=i;
            if(maxx<j) maxx=j;
            apprd[i]=apprd[j]=1;
            soned[j]++;
        }
        roots=0;
        for(i=minx;i<=maxx;i++)
        {
            if(apprd[i]&&soned[i]==0)
            {
                roots++;
                if(roots>1)
                {
                    failed=1;
                    break;
                }
            }
            if(apprd[i]&&soned[i]>1)
            {
                failed=1;
                break;
            }
        }
        if(!roots) failed=1;
        if(failed) printf("Case %d is not a tree.\n",++a);
        else printf("Case %d is a tree.\n",++a);
    }
}

 

可是......

WA的红色无情地刺痛了我的眼........

怎么会这样....

后来,发现,其实一组数据直接输入0 0的时候..它其实应该是一棵树....

没审题成千古恨啊!!!!!!!!!!!!!!

 

然后........再稍微处理了一下,成了:

 

 

#include<cstdio>
#include<cstring>
int apprd[10005],soned[10005],a,minx,maxx,roots,failed;
int main()
{
    int i,j;
    while(1)
    {
        failed=0;
        minx=10005;maxx=-1;
        memset(apprd,0,sizeof(apprd));
        memset(soned,0,sizeof(soned));
        while(1)
        {
            scanf("%d%d",&i,&j);
            if(i==-1) return 0;
            if(!i) break;
            if(minx>i) minx=i;
            if(minx>j) minx=j;
            if(maxx<i) maxx=i;
            if(maxx<j) maxx=j;
            apprd[i]=apprd[j]=1;
            soned[j]++;
        }
        if(minx>maxx)
        {
            printf("Case %d is a tree.\n",++a);
            continue;
        }
        roots=0;
        for(i=minx;i<=maxx;i++)
        {
            if(apprd[i]&&soned[i]==0)
            {
                roots++;
                if(roots>1)
                {
                    failed=1;
                    break;
                }
            }
            if(apprd[i]&&soned[i]>1)
            {
                failed=1;
                break;
            }
        }
        if(!roots) failed=1;
        if(failed) printf("Case %d is not a tree.\n",++a);
        else printf("Case %d is a tree.\n",++a);
    }
}


不仔细看你们可能看不出来吧.......

 

就是对一棵空树的特殊处理....

然后多组数据要把数组什么的该清零清零的就不说了吧微笑

 

Upd:发现过不了一组数据...

1 2  2 3  3 1  4 5  0 0

不信试试?

于是:

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10005
using namespace std;
int cas,minx,maxx,fa[maxn];
bool vis[maxn];
struct node
{
	int v;
	node* nxt;
}*adj[maxn];
int dfs(int x)
{
	int ans=1;
	if(!vis[x]) return -maxn;
	vis[x]=false;
	for(node* p=adj[x];p!=NULL;p=p->nxt)
		ans+=dfs(p->v);
	return ans;
}
void addedge(int u,int v)
{
	node* p=new node;
	p->v=v;p->nxt=adj[u];
	adj[u]=p;
}
int main()
{
    int x,y;
    while(1)
    {
		scanf("%d%d",&x,&y);
		if(x<0) break;
        bool f=false;
		int n=0;
        memset(fa,0,sizeof(fa));
        memset(vis,0,sizeof(vis));
        memset(adj,0,sizeof(adj));
        maxx=max(x,y);minx=min(x,y);
		addedge(x,y);
		fa[y]=x;
		if(!vis[x]) n++;
		vis[x]=true;
		if(!vis[y]) n++;
		vis[y]=true;
        while(1)
        {
			if(!x) break;
			scanf("%d%d",&x,&y);
			if(!x) break;
            if(f) continue;
            if(fa[y]) {f=true;continue;}
            maxx=max(maxx,max(x,y));minx=min(minx,min(x,y));
			addedge(x,y);
            fa[y]=x;
			if(!vis[x]) n++;
			vis[x]=true;
			if(!vis[y]) n++;
			vis[y]=true;
        }
        int cnt=0;
		for(int i=minx;i<=maxx&&!f;i++)
            if(vis[i]&&!fa[i])
			{
				cnt++;
				if(cnt>1||dfs(i)<n) f=true;
			}
		if(!minx&&!maxx) f=false;
        if(f||cnt!=1) printf("Case %d is not a tree.\n",++cas);
        else printf("Case %d is a tree.\n",++cas);
    }
}

 

 

 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值