一笔画问题

本文介绍了一笔画问题的算法实现,通过使用并查集来判断一个图是否可以用一笔画完成。文章提供了一个C++示例代码,详细解释了如何通过减少顶点数量的方式判断是否存在符合条件的连线。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述

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;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值