[kuangbin帶你飛] 專題五 並查集 小希的迷宮 HDU - 1272

上次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

思路:有好久好久都沒有認認真真地專項練習啦, 作爲一個萌新我想還是認認真真地把一個專題一個專題過掉比較好,參加完18西安邀請賽,打了個銅感覺自己好菜呀......。而且熱身也被一道並查集給卡住了(雖然最後發現錯的點並不在並查集上),但依舊改變不了自己菜的事實balabalabala,好了不說了來說這道題吧(依舊是被卡得生活不能自理題, 菜好伐~)。

        本來看到題覺得挺簡單的,裸的加上vis就可以了,但狂WA不止。實在不行了去看了dalao們的博客,發現錯得有兩點... 好吧我覺得第一個實在是不該:

        1.如果一條邊中的兩個點先前就在一個集合中了並且沒有邊, 那麼加上這條邊肯定有環了就有兩條路了這是無疑的;錯的點是在如果一條邊之前出現過,第二次又出現了,那麼也是錯的。這點沒有想到... 簡單得覺得是倆點間的邊是否存在了... 以後需要注意

        2.起始輸入時就是0 0, 也就是空樹。這時也應該輸出Yes。爲什麼我覺得這是題的鍋呢(理不直氣也壯~)。還有這道題POJ 1308根本就是一道題嘛。

代碼:

#include<iostream>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
#define MP(x, y) make_pair((x), (y))
const int maxn = 1e5 + 555;

bool flag, vis[maxn];
int fa[maxn], cnt;

void init(){
    for(int i = 1; i < maxn; i++){
        fa[i] = i;
        vis[i] = 0;
    }
    cnt = 0;
    flag = true;
}

int getfa(int x){
    return fa[x] = fa[x] == x ? x : getfa(fa[x]);
}

void solve(int x){
    vis[x] = 1;
    cnt++;
}

void merge(int x, int y){
    if(!vis[x]) solve(x);
    if(!vis[y]) solve(y);
    int xx = getfa(x);
    int yy = getfa(y);
    if(xx != yy){
        fa[xx] = yy;
        cnt--;
    }
    else
        flag = false;
}

int main(){
    int x, y;
    while(scanf("%d %d", &x, &y), x != -1 && y != -1){
        if(!x && !y){
            printf("Yes\n");
            continue;
        }
        init();
        merge(x, y);
        while(scanf("%d %d", &x, &y), x + y)
            if(flag) merge(x, y);
        if(flag && cnt != 1) flag = false;
        printf("%s\n", flag ? "Yes" : "No");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章