题目链接

描述

A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties.

There is exactly one node, called the root, to which no directed edges point.

Every node except the root has exactly one edge pointing to it.

There is a unique sequence of directed edges from the root to each node.

For example, consider the illustrations below, in which nodes are represented by circles and edges are represented by lines with arrowheads. The first two of these are trees, but the last is not.

  • 输入
    The input will consist of a sequence of descriptions (test cases) followed by a pair of negative integers. Each test case will consist of a sequence of edge descriptions followed by a pair of zeroes Each edge description will consist of a pair of integers; the first integer identifies the node from which the edge begins, and the second integer identifies the node to which the edge is directed. Node numbers will always be greater than zero.The number of test cases will not more than 20,and the number of the node will not exceed 10000.The inputs will be ended by a pair of -1.

  • 输出
    For each test case display the line "Case k is a tree." or the line "Case k is not a tree.", where k corresponds to the test case number (they are sequentially numbered starting with 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.树中的每一个节点的父节点有且仅有一个(根节点除外,根节点没有父节点),每一个节点的孩子节点可以有一个到多个;

2.树是一种从父节点向下指向孩子节点的结构,不能出现一个孩子节点指向其父节点,或则父节点的父节点等情况;

3.对于一棵树来说,有且仅能有一个根节点。

应用并查集的知识来判断,如果要加入的子节点已经有父节点,或则是说要加入的父节点和孩子节点有相同的父节点的话,这都是在加入节点的时候都不满足树的条件的,之后的系欸按就没有必要加入了,因为已经不满足。或则树建成以后,发现不仅仅有一棵树,也不满足。

代码:

#include<stdio.h>
#include<iostream>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
int parent[10000];
int flag;
void init()///初始化,把每个节点的父节点都当作其本身
{
    for(int i=1; i<=10000; i++)
        parent[i]=i;
}

int Find(int a)///递归查找结点a的父节点
{
    if(parent[a]==a) return a;
    else
        return Find(parent[a]);
}
void UpDate(int a,int b)
{
    int x=Find(a);
    int y=Find(b);
    // cout<<"a=="<<a<<"x=="<<x<<"b=="<<b<<"y=="<<y<<endl;
    if(parent[b]!=b||x==y)///表示b在添加父节点a之前已经有父节点,或则a与b有相同的父节点这就构成了环
    {
        flag=1;
    }
    if(x!=y)
    {
        parent[y]=x;
    }
}
int main()
{
    int a,b;
    int op=1;
    init();
    flag=0;
    set<int>s;
    set<int>::iterator it;///为set集合定义一个迭代器
    while(~scanf("%d%d",&a,&b))
    {
        if(a==0&&b==0)///当前这棵树结束的标志
        {
            int sum=0;
            for(it=s.begin(); it!=s.end(); it++)
            {
                if(Find(*it)==*it)///如果他的父节点是他自己,也就意为着他是整棵树的根节点
                    sum++;
                if(sum>1)///根结点的个数多于一个,肯定不是一棵树
                {
                    flag=1;///标记当前的已经不满足一棵树的条件了
                    break;
                }
            }
            if(flag==0)
                printf("Case %d is a tree.\n",op);
            if(flag==1)
                printf("Case %d is not a tree.\n",op);
            s.clear();///set集合清空
            init();///再重新把每个节点的父节点指向其本身
            op++;
            flag=0;
        }
        else if(a==-1&&b==-1)///整个输入结束的标志
            break;
        else
        {
            s.insert(a);
            s.insert(b);
            if(flag==0)
                UpDate(a,b);///只有当前的这个树还满足数的结构在加入判断
            else///如果已经不满足树的结构了,就没有必要在进行了
                continue;
        }
    }
    return 0;
}
posted on 2017-04-19 07:21  渡……  阅读(314)  评论(0编辑  收藏  举报