zoukankan      html  css  js  c++  java
  • NYOJ 42 一笔画

    一笔画问题

    时间限制: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
    来源
    [张云聪]原创
    上传者
    张云聪

     

     

    问题分析:

     
    欧拉定理   如果一个网络是连通的并且奇顶点的个数等于0或2,那么它可以一笔画出;否则它不可以一笔画出。
     
    判断一笔画的方法:
     
      ①是连通的。一个图,如果图上任意二点总有线段连接着,就称为连通的。不是连通的就不能一笔画出。
     
      ②奇点个数是0或者是2。图上线段的端点可以分成二类,奇点和偶数。一个点,以它为端点的线段数是奇数就称为奇点,线段数是偶数就称为偶点。
     
      一个图是否是一笔画就看奇点的个数,奇点个数是 0 或者 2,就是一笔画,否则就不是一笔画。
     
     
    判断连通性 : 并查集 或 深搜  
    http://blog.csdn.net/wdkirchhoff/article/details/41726385
    http://blog.csdn.net/ckpckp/article/details/22071837
    # include<iostream>
    #include<string.h>
    using namespace std;
    int pre[1111],ans[1111];
    int find(int x)
    {
        int r = x; //委托r去寻找x的老大 (保留x的值)
        while(pre[r] != r)
        {
            r = pre[r];   //直到找到老大  然后由x将老大带回
        }
        
        int i = x,j;   //路径压缩,由委托人x开始至老大r结束  递推将路径压缩
        while(i != r)  
        {
            j = pre[i];
            pre[i] = r;
            i = j;
        }
    
        return r;  //返回老大的值
    }
    void join(int x,int y)
    {
        ans[y]++;  //一个数出现一次 说明有一条线
        ans[x]++;
        int fx = find(x);
        int fy = find(y);
        if(fx != fy)  //将两个点连接在一起
        {
            pre[fy] = fx;
        }
    }
    int main()
    {
        int n,p,q,i,j,x,y;
        cin>>n;
        while(n--)
        {
            cin>>p>>q;
            memset(ans,0,sizeof(ans));
            for(i=1;i<=p;i++) //初始化 
            {
                pre[i] = i;
            }
            
            for(i=0;i<q;i++)  //处理数据
            {
                cin>>x>>y;
                join(x,y);
            }
            
              int count1=0,count2=0;
            for(i=1;i<=p;i++)
            {
                if(i==find(i))
                {
                    count1++; //连通性的判断  判断是不是只有一个老大
                }
            }
            
            for(i=1;i<=p;i++)
            {
                if(ans[i]%2==1)
                {
                    count2++; //奇点数目判断
                }
            }
            if(count1==1 && (count2==0||count2==2))
            {
                cout<<"Yes"<<endl;
            }
            else
            {
                cout<<"No"<<endl;
            }
        }
        return 0;
    }
     
  • 相关阅读:
    linux 系统函数 basename和dirname
    写linux脚本你怎么能不知道位置参数!?
    Linux 使用中history 默认记录数不够用了?
    在C/C++中常用的符号
    java23种设计模式之一: 策略模式
    工作中用到的git命令
    注解@Aspect实现AOP功能
    AOP 面向切面 记录请求接口的日志
    javaWeb导出POI创建的多个excel的压缩文件
    nginx的重试机制以及nginx常用的超时配置说明
  • 原文地址:https://www.cnblogs.com/wshyj/p/6440735.html
Copyright © 2011-2022 走看看