一笔画问题

/*描述
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是联通图且无奇度顶点!存在欧拉回路:G是连通图却恰好有两个奇度顶点!
所以首先判断是否联通!
再连通图的基础上,判断有没有奇度顶点,有几个!*/
//并查集 
#include <stdio.h>
#include <string.h>
int pre[1005],s[1005];
int find(int x)
{
	if(x!=pre[x])
	pre[x]=find(pre[x]);
	return pre[x];
}
void join(int x,int y)
{
	int fx,fy;
	fx=find(x);
	fy=find(y);
	if(fx!=fy)
	pre[fx]=fy;
}
int main()
{
	int n,p,q;
	int a,b;
	scanf("%d",&n);
	int i,sum,sum_1;
	while(n--)
	{
		sum=0;
		sum_1=0;
		memset(s,0,sizeof(s));
		scanf("%d%d",&p,&q);
		for(i=1;i<=p;i++)
		pre[i]=i;
		for(i=1;i<=q;i++)
		{
			scanf("%d%d",&a,&b);
			s[a]++;
			s[b]++;
			join(a,b);
		}
		for(i=1;i<=p;i++)
		{
			if(find(i)==i)
			sum++;
			if(s[i]%2!=0)
			sum_1++;
			
		}
		if(sum==1&&(sum_1==0||sum_1==2))
		printf("Yes\n");
		else
		printf("No\n");
	}
	return 0;
}
//深搜 
#include <stdio.h>
#include <string.h>
int e[1005][1005],book[1005];
int sum;
int p,q;
void dfs(int n)
{
	int i;
	book[n]=1;//把该点标记 
	for(i=1;i<=p;i++)
	{
		if(e[n][i]!=0)
		{
			if(!book[i])//进行下一点的搜索 
			dfs(i);
		}
	}
}
int main()
{
	int n,i;
	int a,b;
	int number;
	int c[1005];
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d%d",&p,&q);
		sum=0;
		memset(e,0,sizeof(e));
		memset(book,0,sizeof(book));
		memset(c,0,sizeof(c));
		for(i=1;i<=q;i++)
		{
			scanf("%d%d",&a,&b);
			e[a][b]=e[b][a]=1;
			c[a]++;
			c[b]++;
		}
		dfs(1); 
		int flag=0;
		for(i=1;i<=p;i++)//判断是否连通 
		{
			if(book[i]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag)
		{
			printf("No\n");
		}
		else
		{
			for(i=1;i<=p;i++)
			{
				if(c[i]%2!=0)
				sum++;
			}
			if(sum==0||sum==2)
			printf("Yes\n");
			else
			printf("No\n");
		}
		
	}
	return 0;
}

阅读更多
换一批

没有更多推荐了,返回首页