1. 程式人生 > >並查集------M - 小希的迷宮/N - Is It A Tree?

並查集------M - 小希的迷宮/N - Is It A Tree?

上次Gardon的迷宮城堡小希玩了很久(見Problem B),現在她也想設計一個迷宮讓Gardon來走。但是她設計迷宮的思路不一樣,首先她認為所有的通道都應該是雙向連通的,就是說如果有一個通道連通了房間A和B,那麼既可以通過它從房間A走到房間B,也可以通過它從房間B走到房間A,為了提高難度,小希希望任意兩個房間有且僅有一條路徑可以相通(除非走了回頭路)。小希現在把她的設計圖給你,讓你幫忙判斷她的設計圖是否符合她的設計思路。比如下面的例子,前兩個是符合條件的,但是最後一個卻有兩種方法從5到達8。
在這裡插入圖片描述

Input
輸入包含多組資料,每組資料是一個以0 0結尾的整數對列表,表示了一條通道連線的兩個房間的編號。房間的編號至少為1,且不超過100000。每兩組資料之間有一個空行。
整個檔案以兩個-1結尾。
Output
對於輸入的每一組資料,輸出僅包括一行。如果該迷宮符合小希的思路,那麼輸出"Yes",否則輸出"No"。
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
Yes
Yes
No

這道題很簡單,但是有許多坑點
1>題目中不會給出所有點,只會在給定點來建樹;
2>直接輸入0 0,就是空樹的情況,輸出Yes
3>還有森林(就是多棵樹)和自環應該輸出No

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double PI = acos(-1);
#define pb push_back
#define mp make_pair
#define fi first
#define se second
const int N = 1e5 + 5;

int b[N];
bool vis[N];

int join(int x)
{
    if(b[x] != x){
        b[x] = join(b[x]);
    }
    return b[x];
}

void join1(int x,int y)
{
    int p = join(x);
    int q = join(y);
    if(p != q){
        b[p] = q;
    }
}

int main()
{
    int n,m;
    int MAX = -1;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i = 1;i < N;++i){
            b[i] = i;
            vis[i] = false;
        }
        if(n == -1 && m == -1){
            break;
        }
        if(n == 0 && m == 0){
            printf("Yes\n");
            continue;
        }
        join1(n,m);
        vis[n] = vis[m] = true;
        bool flag = false;
        while(true){
            scanf("%d %d",&n,&m);
            if(n == 0 && m == 0){
                break;
            }
            if(join(n) == join(m)){
                flag = true;
            }else{
                join1(n,m);
            }
            vis[n] = vis[m] = true;
        }
        if(flag){
            printf("No\n");
        }else{
            int cnt = 0;
            for(int i = 1;i < N;++i){
                if(vis[i] && b[i] == i){
                    cnt++;
                }
            }
            if(cnt != 1) printf("No\n");
            else printf("Yes\n");
        }
    }
    return 0;
}

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

據說這道題資料是特別的水,和上道題的程式碼一樣,唯一需要區別的就是 1 1 0 0每個節點有自環是不行的應該輸出not a tree