欧拉回路解决一笔画问题

                          一笔画问题

时间限制: 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
样例输出
No
Yes


【分析】

          一笔画问题是一个运用搜索和欧拉回路才能做出来的题目,如果光用搜索能        做出来,但是会远远的超时,所以不能单单使用搜索来做,其实搜索很多题目都是    要通过剪枝来避免超时的,欧拉回路就是专门解决一笔画问题的。快哭了如果不知道什    么是欧拉回路可以看一看欧拉回路的具体定义,这里简单说一下欧拉回路,在一个    无向图中,如果无向图是连通的,如果有两个奇点(被奇数个线来接着的点),则    必须从其中一个奇点出发,另一个奇点终止;如果奇点不存在或有一个奇点,则可    以从任意点出发,最终一定能走完所以结点,称为欧拉回路。用欧拉回路进行判断    可以减去很多无用功,避免超时大笑

【代码】

#include<stdio.h>
#include<string.h>
#define INF 0x3f3f3f3f
int e[1010][1010],Q,P,flag;
void dfs(int cur,int s)
{
    if(flag==1)
        return ;
    int i;
    if(s==Q)
    {
        flag=1;
        printf("Yes\n");
        return;
    }
    for(i=1;i<=P;i++)
    {
        if(e[cur][i]==1)
        {
            e[cur][i]=0;
            e[i][cur]=0;
            dfs(i,s+1);
            e[cur][i]=1;
            e[i][cur]=1;
        }
    }
    return ;
}
int main()
{
    int N,x;
    scanf("%d",&N);
    while(N--)
    {
        int arr[1010]={0},tmp;
        flag=0,x=0;
        scanf("%d %d",&P,&Q);
        int i,j,a,b;
        memset(e,0,sizeof(e));
        for(i=1;i<=P;i++)
            for(j=1;j<=P;j++)
            if(i==j) e[i][j]=0;
            else e[i][j]=INF;
        for(i=1;i<=Q;i++)
        {
            scanf("%d %d",&a,&b);
            arr[a]++;       // 新定义一个数组用来储存输入的数,出来的次数
            arr[b]++;
            e[a][b]=1;
            e[b][a]=1;
        }
        for(i=1;i<1010;i++)
        {
            if(arr[i]%2==1)  // 求出有多少个奇点(一个点由奇数个线连接)
            {
                tmp=i;
                 x++;
            }
        }
        if(x>2)
        // 如果出来奇数的个数大于2个说明没有结果,他们只有一个入口没有出口,所以超过2个肯定画不完
        {
            printf("No\n");
            continue;
        }
        if(x==2||x==1)
            dfs(tmp,0);     // 如果有2个或1个出现一次的,只可能从一个开始从另一个结束,不然不可能画完
        else
            dfs(1,0);       // 如果都是出现次数大于1,就相当于一个环,从哪开始都一样
        if(flag==0)
            printf("No\n");
    }
    return 0;
}

有问题不用找警察,给我留言就OK了

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值