首页 > 代码库 > Is It A Tree?------HDOJ杭电1325(两种方法,可以用也可以不用并查集!!!!!!详解)

Is It A Tree?------HDOJ杭电1325(两种方法,可以用也可以不用并查集!!!!!!详解)

Problem Description
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.



In this problem you will be given several descriptions of collections of nodes connected by directed edges. For each of these you are to determine if the collection satisfies the definition of a tree or not. 

 

Input
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. 
 

Output
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). 
 

Sample Input
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
 

Sample Output
Case 1 is a tree. Case 2 is a tree. Case 3 is not a tree.
 
这道题乍一看!!!!!!并查集啊!!!!!!@¥%……@…………%¥……#¥%&……%&&%&#%……*&……¥@……&……%&#&……&¥#&&¥&%¥!!!!!!
此处省略六万六千六百六十六个字!!!!!!表达欣喜之情,并查集还是很简单的!!!!!!
对吧!!!!!!
如果对并查集不怎么熟悉的童鞋,咱们来小小介绍下某万能思想:找老大!!!!!!这里有一篇文章,讲的特别好,http://blog.csdn.net/shahongzhou/article/details/8957886,这是链接,大家可以看看!!!!!!
我先剧透一下,就是一级下面还有一级,咱们把他们归结为一个老大,就是b归a管,c归b管,咱们就让c直接归a管,直接找到根节点,嗯,剧透完毕!!!!!!
现在咱们来讲讲这道题,我相信会百度这道题的童鞋一般就两种情况,并查集不会的,还有这题一直WA的,哈哈哈哈哈哈哈哈哈哈!!!!!!23333333333333!!!!!!
笑笑有益身体健康!!!!!!
并查集不会的先去看看上面的链接的知识,然后做一下杭电的畅通工程!!!!!!不过那个畅通工程不一定都是并查集,知识有一题是,哪一题我忘了!!!!!!
这题就是说给一堆数据,一对一对的,ono!!!!!!今天520,讲这么伤心的东西,一对一对!!!!!!不好意思,又偏题了!!!!!!不过我等ACMER屌丝总是要伤感一下的!!!!!!求理解啊!!!!!!继续讲解题目,不停输入a,b,代表b是a的子节点,然后a,b都为0的时候输入结束!
这道题考虑的东西好多啊!!!!!!
坑爹有木有啊!!!!!!
WA的童鞋可以理解的!!!!!!
首先,不能成环!!!!!!
然后不能是树林!!!!!!
最后,不能有入度为2的节点!!!!!!
先贴下代码,大伙好好理解下,代码AC过的:
#include<stdio.h>
#define maxn 100000 + 6
int tree[maxn],bj[maxn];                      //数组e的元素值等于当前序号父级的序号,不一定是树的根
int find(int x)
{                                                            //找树根
    if(tree[x]==x)
        return x;
    else
        return find(tree[x]);
}

int main()
{
    int i,j,k;
    int t,n,m;
    int x,y,num;
    int w=0;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        if(m<0&&n<0)
            break;
        t=0;
        w++;
        if(!(m||n))
            printf("Case %d is a tree.\n",w);
        else
        {
            for(i=1;i<=maxn;i++)
            {
                tree[i]=i;
                bj[i]=0;
            }
            tree[n]=m;
            bj[m]=bj[n]=1;
            while(scanf("%d%d",&m,&n)!=EOF&&(m||n))
            {
                x=find(m);
                y=find(n);
                if(x==y)
                    t=1;                                             //判断是否是环
                else
                    tree[n]=m;                                       //即使存在元素更改了父级也不影响树的个数
                bj[m]=bj[n]=1;
            }
            if(t==1)
                printf("Case %d is not a tree.\n",w);
            else
            {
                num=0;
                for(i=1;i<=maxn;i++)
                {
                    if(bj[i]==1&&tree[i]==i)                      //统计树根个数,为1时才符合题意
                    {
                        num++;
                        if(num>1)
                            break;
                    }
                }
                if(num>1)
                    printf("Case %d is not a tree.\n",w);
                else
                    printf("Case %d is a tree.\n",w);
            }
        }
    }
    return 0;
}

都说了是并查集的题目,所以并查集的做法先来一遍,现在小弟来种不需要并查集的方法!!!!!!
直接上代码!!!!!!同AC过的:
#include "stdio.h"
#include<iostream>
#define m 100001
using namespace std;
int main()
{
    int i,j,k;
    int a,b,flag;
    int tree[m];
    int v[m];
    int ans=1,flag2;
    while(cin>>a>>b)
    {
        if(a<0&&b<0)
            break;
        flag=0;
        flag2=0;
        memset(tree,0,m-1);
        memset(v,0,m-1);
        int e=0;
        while(a&&b)
        {
            flag2=1;
            if(!v[a])
            {
                v[a]=1;
                e++;
            }
            if(!v[b])
            {
                v[b]=1;
                e++;
            }
            e--;
            if(tree[b]==0)//b is root
                tree[b]=1;
            else
            {
                flag=1;
                break;
            }
            cin>>a>>b;
        }
        while(a&&b)
        {
            scanf("%d %d",&a,&b);
        }
        if((!flag&&e==1)||flag2==0)
            printf("Case %d is a tree.\n",ans);
        else
            printf("Case %d is not a tree.\n",ans);
        ans++;
    }
    return 0;
}

具体为什么???!!!自个儿理解去吧!!!!!!
好啦!!!!!!
卤煮不容易啊!!!!!!在这么伤感的日子(520)里还要写题解造福大伙,你们是不是觉得我好伟大!!!!!!O(∩_∩)O哈哈~
还是那句话,如果发现bug,还请指出,不胜感激,晚安啦!!!!!!