Play on Words-uva 精短欧拉回路

思路:先分析,特殊的字母,可能有的字母是当开头个数+1=当结尾个数,那么这个字母一定是开头,同理另一个特殊字母就是作为结尾的

之后其余的字母的话只可能是开头=结尾个数,如果有任何一个字母当开头的个数和结尾个数只差为2,那么回路一定不成立!

之后是构建DFS遍历

遍历的思路就是 用G[i][j]表示字母i,j是连通的!

遍历的起点我们分为2个步骤,一个是这个图是个环路

第二个是一条线性图

环路的话从哪里都可以开始遍历

线形图的话最好从开头进行遍历

一直遍历到结尾

之后看有没有没有遍历到的节点

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define LEN 100 + 10
#define MAX_SIZE  1000 + 10
int G[LEN][LEN];
int front[LEN];
int back[LEN];
int vis[LEN];
int dfs(int u)
{
    vis[u]=1;
    for(int i=0;i<LEN;i++)
        if(G[u][i]&&!vis[i])/*如果是连通的话*/
    {
        dfs(i);
    }
}
int main()
{
    int N;
    scanf("%d",&N);
    for(int cases=1;cases<=N;cases++)
    {
        int n,ok=1;
        scanf("%d",&n);
        memset(front,0,sizeof(front));
        memset(back,0,sizeof(back));
        memset(G,0,sizeof(G));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            char word[MAX_SIZE];
            scanf("%s",word);
            int L=strlen(word);
            G[word[0]-'0'][word[L-1]-'0']++;
            front[word[0]-'0']++;
            back[word[L-1]-'0']++;
        }
        int num1=0,num2=0;
        for(int i=0;i<LEN;i++)
        {
            if(front[i]!=back[i])
            {
                if(front[i]==back[i]+1)
                    num1++;
                else if(front[i]+1==back[i])
                    num2++;
                else
                {
                    ok=0;
                    break;
                }
            }
        }
        if(num1&&num2&&num1+num2>2)
        ok=0;
        if(ok){/*开头和结尾只能有一个*/
        /*开始遍历!*/
        int ok1=0;
        int ok2=0;
        for(int i=0;i<LEN;i++)
        {
            if(num1==0&&num2==0&&front[i])
            {
                /*如果是一个回路的图*/
                   dfs(i);
                   break;
            }
            else if(front[i]>back[i])
            {
                  dfs(i);
                   break;
            }
        }
        num1=0;num2=0;
        for(int i=0;i<LEN;i++)
        {
            if(!vis[i]&&front[i]){ok=0;break;}
            if(!vis[i]&&back[i]){ok=0;break;}
        }
        if(ok) printf("Ordering is possible.\n");
        else printf("The door cannot be opened.\n");
        }
        else printf("The door cannot be opened.\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值