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;
            }
        }
    }
}


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