hdu 1325 Is It A Tree?(並查集)


Is It A Tree?

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 421 Accepted Submission(s): 157

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.
 

同見poj(1038)

程序分析(轉載):

  這道題跟小希的迷宮有很大的相似吧,只是一個是無向圖一個是有向圖。也是給你那些結點之間的信息,然后讓你判斷是不是一顆樹罷了,用樹的定義來 判斷吧,無環,n個結點最多有n-1條邊,不然就會有環。只有一個入度為0的結點,不存在入度大於1的結點。這些也足以判斷是否為一棵樹了吧。不過要注意 一些特殊數據的情況,空樹也是樹。比如輸入0 0。

解決方法:

  其實也可以不用並查集,這樣就可以直接按照上面的條件來統計,就可以判斷是不是一顆樹了。

自我感言:額,這道題目關鍵就是判斷樹的那幾個標准,1,無環;2,除了根,所有的入度為1,根入度為0;3,這個結構只有一個根,不然是森林了。

這是三個標准拿捏好,再注意這里空樹也是樹。基本上就ok了。。

坑爹的是下邊的代碼可以在hdu上通過,而不能在poj上通過。。。。。看了discuss才知道 1 1 0 0 不能是樹。

下面幾種情況要注意了。。。。

1: 0 0 空樹是一棵樹
2: 1 1 0 0 不是樹 不能自己指向自己
3: 1 2 1 2 0 0 不是樹....自己開始一直在這么WA  好郁悶 重復都不行呀~~5555
4: 1 2 2 3 4 5 不是樹  森林不算是樹(主要是注意自己)
5: 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 1  注意 一個節點在指向自己的父親或祖先 都是錯誤的 即 9-->1 錯
6: 1 2 2 1 0 0 也是錯誤的
這樣基本上就可以在poj上通過了,poj(1038)題

這是hdu上通過的代碼:
View Code
#include <stdio.h>

const int max_num = 100000+10;
typedef struct
{
    int num,root,conn;//數據、根、入度
}Node;

Node node[max_num];

void init()
{
    for(int i = 0; i < max_num; i++)
    {
        node[i].conn = 0;//入度初始化為0
        node[i].root= i;//根記錄為自身
        node[i].num=0;//標記數字是否被使用過,0:沒有被使用過,1:使用過了
    }
}

int find_root(int a)
{
    if(node[a].root!=a)
        return node[a].root = find_root(node[a].root);
    return node[a].root;
}

void union_set(int a,int b)
{
    a = find_root(a);
    b = find_root(b);
    if(a==b)//同一個根,說明是在同一個樹下
    return;
    node[b].root=a;//把b的根賦為a的根,此時a已經是根,num==root
}

int main()
{
    int n,m;
    int i = 1;
    bool flag=true;//true:是個樹,false:不是樹
    init();
    while(scanf("%d%d",&n,&m)!=EOF&&n>=0&&m>=0)
    {
        if(!flag&&n!=0&&n!=0)continue;//已經確定不是樹了,就繼續循環
        if(n==0&&m==0)
        {
            int root_num=0;
            for(int j = 1; j < max_num;j++)
            {
                //判斷是否為森林,如果,root_num用來記錄根的數目
                if(node[j].num && find_root(j)==j)
                root_num++;
                if(node[j].conn>1)//如果出現某個節點的入度超過1,不是樹
                {
                    flag = false;
                    break;
                }
            }
            if(root_num>1)//連通分支大於1,是森林不是樹
                flag=false;
            if(flag)
            printf("Case %d is a tree.\n",i++);
            else printf("Case %d is not a tree.\n",i++);
            flag = true;
            init();
            continue;
        }
        if(m!=n&&find_root(n)==find_root(m))
        flag = false;
        else
        {
            //將m,n,記錄為節點
            node[m].num = 1;
            node[n].num = 1;
            node[m].conn++;//入度增加一
            union_set(n,m);
        }
    }
    return 0;
}

中間只是稍作修改,把if(m!=n&&find_root(n)==find_root(m))改成了if((m!=n&&find_root(n)==find_root(m))||m==n)就在poj上通過了

 

View Code
#include <stdio.h>

const int max_num = 100000+10;
typedef struct
{
    int num,root,conn;//數據、根、入度
}Node;

Node node[max_num];

void init()
{
    for(int i = 0; i < max_num; i++)
    {
        node[i].conn = 0;//入度初始化為0
        node[i].root= i;//根記錄為自身
        node[i].num=0;//標記數字是否被使用過,0:沒有被使用過,1:使用過了
    }
}

int find_root(int a)
{
    if(node[a].root!=a)
        return node[a].root = find_root(node[a].root);
    return node[a].root;
}

void union_set(int a,int b)
{
    a = find_root(a);
    b = find_root(b);
    if(a==b)//同一個根,說明是在同一個樹下
    return;
    node[b].root=a;//把b的根賦為a的根,此時a已經是根,num==root
}

int main()
{
    int n,m;
    int i = 1;
    bool flag=true;//true:是個樹,false:不是樹
    init();
    while(scanf("%d%d",&n,&m)!=EOF&&n>=0&&m>=0)
    {
        if(!flag&&n!=0&&n!=0)continue;//已經確定不是樹了,就繼續循環
        if(n==0&&m==0)
        {
            int root_num=0;
            for(int j = 1; j < max_num;j++)
            {
                //判斷是否為森林,如果,root_num用來記錄根的數目
                if(node[j].num && find_root(j)==j)
                root_num++;
                if(node[j].conn>1)//如果出現某個節點的入度超過1,不是樹
                {
                    flag = false;
                    break;
                }
            }
            if(root_num>1)//連通分支大於1,是森林不是樹
                flag=false;
            if(flag)
            printf("Case %d is a tree.\n",i++);
            else printf("Case %d is not a tree.\n",i++);
            flag = true;
            init();
            continue;
        }
        if((m!=n&&find_root(n)==find_root(m))||m==n)
        flag = false;
        else
        {
            //將m,n,記錄為節點
            node[m].num = 1;
            node[n].num = 1;
            node[m].conn++;//入度增加一
            union_set(n,m);
        }
    }
    return 0;
}

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM