1. 程式人生 > >小希的迷宮-並查集

小希的迷宮-並查集

思路 rdo NPU 連通 長時間 false sample class 應該

原題鏈接:https://vjudge.net/problem/11138/origin

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

題解:並查集,感覺是道水題,不過我花了好長時間,這道題有個坑點,就是可能會有多個集合,這個不能忽視,要在結束時遍歷一下.

#include <bits/stdc++.h>
const int N=1e5+5;
using namespace std;
int se[N];
int ma[N];
int maxx=0;
//int m[N][2];
int fd(int a){
    int x=a;
    while(se[x]!=x){
        x=se[x];
        for(int i=a,j;i!=x;i=j){
            j=se[i];
            se[i]=x;
        }

    }
    return x;
}
bool join(int a,int b){
    int fa=fd(a);
    int fb=fd(b);
    if(fa==fb) return false;
    se[fa]=fb;
    return true;
}
void wait(){
    int a,b;
    while(~scanf("%d%d",&a,&b)&&a!=0);
    printf("No\n");
    memset(ma,0,sizeof(ma));
    maxx=0;
}
int main(){
    int a,b;
    while(~scanf("%d%d",&a,&b)&&a!=-1){
        if(a==0&&b==0){
            int ans=0;
            for(int i=1;i<=maxx;i++) if(se[i]==i&&ma[i]==1) ans++;//就是這裏,萬惡之源,結束時要遍歷看看有幾個集合
            if(ans>1) printf("No\n");
            else printf("Yes\n");
            memset(ma,0,sizeof(ma));
            maxx=0;
            continue;
        }
        maxx=max(a,max(b,maxx));
        if(ma[a]==0) ma[a]=1,se[a]=a;
        if(ma[b]==0) ma[b]=1,se[b]=b;
        if(!join(a,b)) wait();
    }
}

小希的迷宮-並查集