zoukankan      html  css  js  c++  java
  • NYOJ 42 一笔画问题 (并查集+欧拉回路 )

    题目链接

    描述

    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

    分析:

    如果要想能够一笔画出来,这个图肯定是一个连通图,就是说所有的点都连在一块,如果用并查集的思想理解的话就是所有的点有一个共同的父节点。

    然后就是要满足欧拉回路的思想:

    欧拉图:节点度数全部为偶数;半欧拉图:有且只有两个度数为奇数的节点,这两种图都可以一笔画出,也就是说节点度为奇数的应该有0个或2个。

    补充一下有向图的无向图的欧拉图:

    1.无向连通图G是欧拉图,当且仅当G不含奇数度结点(G的所有结点度数为偶数);

    2.无向连通图G含有欧拉通路,当且仅当G有零个或两个奇数度的结点;

    3.有向连通图D是欧拉图,当且仅当该图为连通图且D中每个结点的入度=出度

    4.有向连通图D含有欧拉通路,当且仅当该图为连通图且D中除两个结点外,其余每个结点的入度=出度,且此两点满足deg-(u)-deg+(v)=±1。(起始点s的入度=出度-1,结束点t的出度=入度-1 或两个点的入度=出度)

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    int parent[1001];
    int du[1001];
    int n,m;
    void init()
    {
        for(int i=1; i<=n; i++)
            parent[i]=i;
        memset(du,0,sizeof(du));
    }
    int Find(int x)
    {
        if(x==parent[x])
            return x;
        else
            return parent[x]=Find(parent[x]);
    }
    
    void He(int a,int b)
    {
        int x=Find(a);
        int y=Find(b);
        if(x!=y)
            parent[x]=y;
    }
    int main()
    {
        int T,a,b;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            init();
            while(m--)
            {
                scanf("%d%d",&a,&b);
                du[a]++;///每个点的度都应该加
                du[b]++;
                He(a,b);///并查集将两个点合并起来
            }
            int sum=0,data=0;
            for(int i=1; i<=n; i++)
            {
                if(parent[i]==i)///找出父节点是本身的所有点
                    sum++;
                if(du[i]&1)///度为奇数的节点个数
                    data++;
            }
            // cout<<"sum==="<<sum<<endl;
            if(sum>1)///没有将所有的点联通起来
            {
                printf("No
    ");
                continue;
            }
            //cout<<data<<"   data--"<<endl;
            if(data==0||data==2)///满足度为奇数的点的个数是0或2
                printf("Yes
    ");
            else
                printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    LeetCode 485. Max Consecutive Ones
    LeetCode 367. Valid Perfect Square
    LeetCode 375. Guess Number Higher or Lower II
    LeetCode 374. Guess Number Higher or Lower
    LeetCode Word Pattern II
    LeetCode Arranging Coins
    LeetCode 422. Valid Word Square
    Session 共享
    java NIO
    非阻塞IO
  • 原文地址:https://www.cnblogs.com/cmmdc/p/6781947.html
Copyright © 2011-2022 走看看