(歐拉圖 並查集 圖論) nyoj 42-一筆畫問題

題目描述:

zyc從小就比較喜歡玩一些小遊戲,其中就包括畫一筆畫,他想請你幫他寫一個程序,判斷一個圖是否可以用一筆畫下來。html

規定,全部的邊都只能畫一次,不能重複畫。node

 

輸入描述:

第一行只有一個正整數N(N<=10)表示測試數據的組數。
每組測試數據的第一行有兩個正整數P,Q(P<=1000,Q<=2000),分別表示這個畫中有多少個頂點和多少條連線。(點的編號從1到P)
隨後的Q行,每行有兩個正整數A,B(0<A,B<P),表示編號爲A和B的兩點之間有連線。

輸出描述:

若是存在符合條件的連線,則輸出"Yes",
若是不存在符合條件的連線,輸出"No"。

樣例輸入:

2
4 3
1 2
1 3
1 4
4 5
1 2
2 3
1 3
1 4
3 4

樣例輸出:

No
Yes


這是一個歐拉圖的應用,思路以下:ios

1)首先判斷是否都在一個集合中,由於這樣才能一筆畫,若是是在兩個不一樣的集合中(即被分紅兩個圖,而這兩個圖不連通),那就最少兩筆畫,不符合要求。測試

2)在一個前提下,判斷奇點數是否爲0或2(一個點的入度和出度的和爲0或2),這樣才能一筆畫。spa

C++代碼:code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1002;
int father[maxn],node[maxn];
int Find(int x){
    while(x != father[x]){
        father[x] = father[father[x]];
        x = father[x];
    }
    return x;
}
void Union(int a,int b){
    int ax = Find(a);
    int bx = Find(b);
    if(ax != bx){
        father[ax] = bx;
    }
}
int main(){
    int N;
    scanf("%d",&N);
    int p,q;
    int a,b;
    while(N--){
        scanf("%d%d",&p,&q);
        for(int i = 1; i <= p; i++){
            father[i] = i;
        }
        memset(node,0,sizeof(node));
        for(int i = 0; i < q; i++){
            scanf("%d%d",&a,&b);
            Union(a,b);
            node[a]++;
            node[b]++;
        }     
        int cnt = 0,cnt1 = 0;
        bool flag1 = false,flag2 = false;
        for(int i = 1; i <= p; i++){
            if(father[i] == i){
                cnt++;
                if(cnt == 2){
                    flag1 = true;
                }
            }
            if(node[i] % 2) cnt1++;
        }
        if(cnt1 != 0 && cnt1 != 2) flag2 = true;
        if(!flag1 && !flag2) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

 

參考連接:http://www.javashuo.com/article/p-spbwoocg-ct.htmlhtm

相關文章
相關標籤/搜索