nyoj_42_一笔画问题_201403181935

 

一笔画问题

时间限制: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 有 2k 个奇顶点,那么它可以用 k 笔画成,并且至少要用 k 笔画成[2]。
  */
代码如下:
 1 #include <stdio.h>
 2 #include <string.h>
 3 int pre[1010],deg[1010];
 4 int find(int x)
 5 {
 6     int t,r;
 7     r=x;
 8     while(r!=pre[r])
 9     r=pre[r];
10     while(x!=r)
11     {
12         t=pre[x];
13         pre[x]=r;
14         x=t;        
15     }
16     return r;
17 }
18 int main()
19 {
20     int T;
21     scanf("%d",&T);
22     while(T--)
23     {
24         int i,j,a,b,pa,pb,p,q,num=0,count=0;
25         memset(deg,0,sizeof(deg));
26         scanf("%d %d",&p,&q);
27         for(i=0;i<=p;i++)
28         pre[i]=i;
29         for(i=0;i<q;i++)
30         {
31             scanf("%d%d",&a,&b);
32             deg[a]++;
33             deg[b]++;
34             pa=find(a);
35             pb=find(b);
36             if(pa!=pb)
37             {
38                 pre[pa]=pb;
39                 count++;
40             }
41         }
42         for(i=1;i<=p;i++)
43         {
44             if(deg[i]&1)
45             num++;
46         }
47         if(num==2||num==0)
48         {
49             if(count==p-1)
50             printf("Yes
");
51             else
52             printf("No
");
53         }
54         else
55         printf("No
");        
56     }
57     return 0;
58 }


并查集+图的连通性

原文地址:https://www.cnblogs.com/xl1027515989/p/3608583.html