描述
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
这道题是一个欧拉回路的问题,我错了好几遍,就不信自己的图论水平了,最后弄出来。都写在代码里面了
#include<cstdio>
#include<cstring>
using namespace std;
int father[1005];
int find(int i)
{
if(i==father[i])
return i;
else
return father[i]=find(father[i]);
}
void uni(int i,int j)
{
int a,b;
a=find(i);
b=find(j);
father[a]=b;
}
int main()
{
int t,n,m,i,j,k,l,a,b,sum[1005];
scanf("%d",&t);//多次输入数据
while(t--)
{
scanf("%d %d",&n,&m);//输入顶点个数和边的条数
for(i=1; i<=n; i++)
father[i]=i;//并查集的经典初始化
memset(sum,0,sizeof(sum));//记录出度和入度的数组
l=n;
for(i=1; i<=m; i++)
{
scanf("%d %d",&a,&b);//只要输入一次,就查找一次.
if(find(a)!=find(b))//如果这两条边不在同一个集合里面,那么说明这是一条有用的新边,以前没有走过
{
l--;//链接一条有用的新边肯定是一个旧定点和一个新顶点,然后你的顶点个数减一
uni(a,b);//将新边合并进去。
}
sum[a]++;//出度和入度的记录
sum[b]++;
}
if(l!=1)
printf("No\n");//举个例子:5个顶点4条边一样,判断边的个数是不是比顶点的个数少一个
else
{
k=0;
for(i=1; i<=n; i++)
if(sum[i]%2)//判断存在多少个奇度顶点
k++;
if(k==0||k==2)//欧拉回路要么两个奇度顶点,要么没有
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}