• nyoj 42-一笔画问题 (欧拉图 && 并查集)


    42-一笔画问题


    内存限制:64MB 时间限制:3000ms Special Judge: No
    accepted:10 submit:25

    题目描述:

    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 void my_init()
     2 {
     3     for(int i = 1; i <= n; ++ i)
     4         pre[i] = i;
     5 }
     6 
     7 int my_find(int x)
     8 {
     9     int n = x;
    10     while(n != pre[n])
    11         n = pre[n];
    12     int i = x, j;
    13     while(pre[i] != n)
    14     {
    15         j = pre[i];
    16         pre[i] = n;
    17         i = j;
    18     }
    19     return n;
    20 }
    21 
    22 void my_join(int a, int b)
    23 {
    24     int n1 = my_find(a), n2 = my_find(b);
    25     if(n1 != n2)
    26         pre[n1] = n2;
    27 }

    C/C++代码实现(AC):

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <stack>
     7 #include <map>
     8 #include <queue>
     9 #include <set>
    10 
    11 using namespace std;
    12 const int MAXN = 1010;
    13 int pre[MAXN], n, m, flag1, flag2, cnt, node[MAXN], cnt2;
    14 
    15 void my_init()
    16 {
    17     for(int i = 1; i <= n; ++ i)
    18         pre[i] = i;
    19 }
    20 
    21 int my_find(int x)
    22 {
    23     int n = x;
    24     while(n != pre[n])
    25         n = pre[n];
    26     int i = x, j;
    27     while(pre[i] != n)
    28     {
    29         j = pre[i];
    30         pre[i] = n;
    31         i = j;
    32     }
    33     return n;
    34 }
    35 
    36 void my_join(int a, int b)
    37 {
    38     int n1 = my_find(a), n2 = my_find(b);
    39     if(n1 != n2)
    40         pre[n1] = n2;
    41 }
    42 
    43 int main()
    44 {
    45 
    46     int t;
    47     scanf("%d", &t);
    48     while(t --)
    49     {
    50         flag1 = 0, flag2 = 0, cnt = 0, cnt2 = 0;
    51         scanf("%d%d", &n, &m);
    52         memset(node, 0, sizeof(node));
    53         my_init();
    54         for(int i = 0; i < m; ++ i)
    55         {
    56             int a, b;
    57             scanf("%d%d", &a, &b);
    58             my_join(a, b);
    59             node[a] ++;
    60             node[b] ++;
    61         }
    62         for(int i = 1; i <= n; ++ i)
    63         {
    64             if(pre[i] == i)
    65             {
    66                 cnt ++;
    67                 if(cnt == 2)
    68                     flag1 = 1;
    69             }
    70             if(node[i]&1) cnt2 ++;
    71         }
    72         if(cnt2 != 0 && cnt2 != 2) flag2 = 1;
    73         if(!flag1 && !flag2) printf("Yes
    ");
    74         else printf("No
    ");
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    ccf 201604-3 路径解析
    ccf 201609-3 炉石传说
    ccf 201612-3 权限查询
    ccf 201709-3 JSON查询
    ccf 201703-3 Markdown
    POJ 3259 -- Wormholes
    Bellman-Ford 单源最短路径算法
    【oracle】oracle启动和关闭步骤
    【Excel】Excel根据单元格背景色求和
    【Oracle】Oracle时间日期格式
  • 原文地址:https://www.cnblogs.com/GetcharZp/p/9091778.html
Copyright © 2020-2023  润新知