一笔画问题
时间限制: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
分析:
一笔画问题,就是欧拉通路问题:经过每条边,且每条边只经过一次。
关于欧拉通路是否存在的判断条件是:在一个连通的无向图中,如果所有的顶点的度为偶数,或者有且仅有连个顶点的度为奇数,则存在欧拉通路。
(1)判断是否连通,用并查集。
(2)看是否满足欧拉通路的条件:看度为奇数的顶点的个数。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int p[1010],d[1010];
int find(int x)
{
return x==p[x]?x:p[x]=find(p[x]);
}
int main()
{
int t;
int n,m,u,v;
scanf("%d",&t);
while(t--)
{
memset(d,0,sizeof(d));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
p[i]=i;
int xx,yy,flag=1;
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
d[u]++;d[v]++;
xx=find(u);yy=find(v);
if(xx!=yy)
p[xx]=yy;
}
xx=find(1);
for(int i=1;i<=n;i++)
{
if(xx!=find(n))
{
flag=0;
break;
}
}
if(!flag)
{
printf("No\n");
continue;
}
int num=0;//奇度点数
for(int i=1;i<=n;i++)
{
if(num>2) break;
if(d[i]&1)
num++;
}
if(num==0 || num==2)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}