原来想的只是个简单欧拉回路问题 没想到wa了两次 最后才知道还要判定是不是通路的问题, 这就要用到并查集了
并查集:参考网址http://www.nocow.cn/index.php/并查集 简而言之就是将一些点归到尽量少的集合当中去(纯属个人看法,有什么不对的地方欢迎指导);
用了并查集之后,可以通过查询每个点的祖先是不是同样的一个数, 如果是, 那就表明这些点构成了一个回路, 如果不是那就没有构成一个通路;
代码:
/*
描述
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<stdio.h>
#include<string.h>
int father[2002], s[2002];
int find( int x )//找到祖先的祖先, 根节点
{
if( father[x] != x ) father[x] = find(father[x]); //将每一个数对应的祖先都赋给对应的序号内
return father[x];
}
int merch( int a, int b )
{
a = find(a);
b = find(b);
if( a!= b ) father[a] = b;
}
int main()
{
int t, p, q, a, b, i;
scanf( "%d", &t );
while( t -- )
{
scanf( "%d%d", &p, &q );
memset( s, 0, sizeof(s) );
for( i = 1; i <= p; i ++ )
father[i] = i; //初始化将每一个数的祖先都定义为他自己
for( i = 0; i < q; i ++ )
{
scanf( "%d%d", &a, &b );
++s[a], ++s[b];
merch( a, b);
}
int flag = 0, ok = 0;
for( i = 1; i <= p; i ++ )
{
if( father[i] == i ) flag++; //如果有自己等于自己的那么他就是一个根节点(原始祖先)
if( s[i]&1 ) ++ok;
if( flag >1 ) {
ok = 3;
break;
}
}
//for( i = 1; i <= p; i ++ )
//printf( "%d..", father[i] );
if( flag == 1&&( ok == 0||ok==2 ) )
printf( "Yes\n" );
else
printf( "No\n" );
}
}