nyoj42 一筆畫問題(歐拉回路+並查集)

一筆畫問題

時間限制:3000 ms  |  內存限制:65535 KB
難度:4
描述

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

規定,所有的邊都只能畫一次,不能重複畫。

 

輸入
第一行只有一個正整數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

先來介紹一下關於歐拉回路判定定理的知識點

定理以及推論:
無向圖G 存在歐拉通路的充要條件是:
G 爲連通圖,並且G 僅有兩個奇度結點(度數爲奇數的頂點)或者無奇度結點。
推論5.1:
1) 當G 是僅有兩個奇度結點的連通圖時,G 的歐拉通路必以此兩個結點爲端點。
2) 當G 是無奇度結點的連通圖時,G 必有歐拉回路。
3) G 爲歐拉圖(存在歐拉回路)的充分必要條件是G 爲無奇度結點的連通圖。


定理5.2


有向圖D 存在歐拉通路的充要條件是:
D 爲有向圖,D 的基圖連通,並且所有頂點的出度與入度都相等;或者除兩個頂點外,其餘
頂點的出度與入度都相等,而這兩個頂點中一個頂點的出度與入度之差爲1,另一個頂點的出度
與入度之差爲-1。
推論5.2:
1) 當D 除出、入度之差爲1,-1 的兩個頂點之外,其餘頂點的出度與入度都相等時,D 的
有向歐拉通路必以出、入度之差爲1 的頂點作爲始點,以出、入度之差爲-1 的頂點作爲
終點。
2) 當D 的所有頂點的出、入度都相等時,D 中存在有向歐拉回路。
3) 有向圖D 爲有向歐拉圖的充分必要條件是D 的基圖爲連通圖,並且所有頂點的出、入度
都相等。
看了上面的理論會發現這個題目很好理解 關於理論不懂得地方 自己可以手動畫一下圖就會一目瞭然了


瞭解了上面的知識過後 來分析下這個題目 
關於圖的連通性用並查集來判斷 當一個節點的父節點還是本身的話證明這個圖不連通
判斷圖的連通性過後 根據出度和入度去判定是否存在歐拉回路

java代碼 這個題目沒用到並查集 不過也可以使用並查集去判斷連通性
package bfs;

import java.util.Arrays;
import java.util.Scanner;

/**
 *
 */
public class Main42 {
    static int p,q;
    static int a[][]=new int[1000+10][1000+10];
    static int pd[]=new int[1000+10];
    static boolean vis[]=new boolean[1000+10];
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        int t=scanner.nextInt();
        while (t-->0){
            p=scanner.nextInt();
            q=scanner.nextInt();
            init();
            Arrays.fill(pd,0);
            for (int i=0;i<q;i++){
                int u=scanner.nextInt();
                int v=scanner.nextInt();
                a[u][v]=1;
                a[v][u]=1;
                pd[u]++;
                pd[v]++;
            }
            //判斷是否是連通圖
            Arrays.fill(vis,false);
            dfs(1);
            boolean flag=true;
            for (int i=1;i<=p;i++){
                if (!vis[i]){
                    flag=false;
                    break;
                }
            }
            int sum=0;
            for (int i=1;i<=p;i++){
                if (pd[i]%2==1){
                    sum++;
                }
            }
            if(sum!=0&&sum!=2){
                flag = false;
            }
            if(flag)
                System.out.println("Yes");
            else System.out.println("No");
        }
    }

    private static void dfs(int s) {
        vis[s]=true;
        for (int i=0;i<=p;i++){
            if (i!=s&&a[s][i]==1&&!vis[i]){
                dfs(i);
            }
        }
    }

    private static void init() {
        for (int i=0;i<1000+10;i++){
            for (int j=0;j<1000+10;j++){
                a[i][j]=0;
            }
        }
    }
}


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