hdoj1116【欧拉回路】

题意:
应该是求一个路径让所有的单词能够首尾连起来,不需要头和尾的单词也连起来。。。应该很容易懂吧。。。我这里讲的好烂。。
思路:
从欧拉回路的定义引申过来。
1. 连通。
2. 入度和出度问题。

问题就是怎么建图???
N(1e5)条边啊。那肯定是邻接表建图。
具体处理呢?对于一个单词,肯定是考虑首尾,单词都是小写字母(lowercase characters),所以首尾的单词肯定会重复啊,但是邻接表可以确定边。但是1e5的量好大。等等,我为什么要建图啊??
只是判个连通,我用个并查集艹一下就好了?所以何必建图????
建图没有意义啊!!!
但是你怎么并,元素是什么?要满足尾对首才可以。我们干嘛去考虑位置的呢??我们只要考虑到他给我的单词的第一个个最后一个是一定连接的,所以也一定是一起的。然后后来我们去考虑这样的两个单词ad,ca,我是特意反了一下,我想说的是,遍历下来,a-d一个集合,后来find(c)=c,find(a)=d,在连通方便这样是解释的通的,但是如果是ad,ac,就有点。。。不行。。。。这样是连通么???不是啊,但用了并查集是连通了。。。所以还有个条件是判断度数,在这里应该是非常能卡掉的。
然后度的话,这里不是要考虑一个欧拉回路,这里相当于只是一个一笔画或者欧拉回路。所以只要说明中间的点的入度和出度是相等的,或者起点的入度+1=出度&&终点的入度=出度+。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PI;
typedef pair< PI, int> PII;
const double eps=1e-5;
const double pi=acos(-1.0);
const int mod=1e9+7;
const int INF=0x3f3f3f3f;


int pre[35];
char ss[1010];

int fd(int x)
{
    int r=x;
    while(r!=pre[r])
    {
        r=pre[r];
    }
    int i=x,j;
    while(pre[i]!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;
}

void Union(int a,int b)
{
    int aa=fd(a);
    int bb=fd(b);
    if(aa!=bb){
        pre[aa]=bb;
    }
}

int main()
{
    int in[35];
    int out[35];
    bool vis[35];
    int T,i,x,y,n;
    cin>>T;
    while(T--)
    {
        scanf("%d",&n);
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(vis,0,sizeof(vis));
        for(i=0;i<26;i++)
            pre[i]=i;

        for(i=0;i<n;i++){
            scanf("%s",ss);
            x=ss[0]-'a';
            y=ss[strlen(ss)-1]-'a';
            Union(x,y);
            out[x]++;
            in[y]++;
            vis[x]=vis[y]=1;
        }

        int flag=0;
        int ft=0;
        int ed=0;
        int own=0;
        for(i=0;i<26;i++)
        {
            if(vis[i]){
                if(pre[i]==i)
                    own++;                  
                if(in[i]!=out[i]){
                    if(in[i]==out[i]+1)
                        ft++;
                    else if(in[i]+1==out[i])
                        ed++;
                    else
                        flag=1;
                }
                if(own>1){
                    flag=1;
                    break;
                }
            }
        }
        if(flag)
            printf("The door cannot be opened.\n"); 
        else if((ft==1&&ed==1)||(ft==0&&ed==0))
            printf("Ordering is possible.\n");
        else
            printf("The door cannot be opened.\n");
    }
    return 0;
}

转载于:https://www.cnblogs.com/keyboarder-zsq/p/5934443.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值