zoukankan      html  css  js  c++  java
  • 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.
    "); 
            else if((ft==1&&ed==1)||(ft==0&&ed==0))
                printf("Ordering is possible.
    ");
            else
                printf("The door cannot be opened.
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    如何判断轮廓是否为圆(算法更新)
    近期购置的CV&AI类图书梳理
    基于OpenCV实现“钢管计数”算法,基于Csharp编写界面,并实现算法融合
    大厂们的 redis 集群方案
    redis 突然大量逐出导致读写请求block
    Docker 1.13 管理命令
    玩转 Ceph 的正确姿势
    Docker 常用命令
    git常用命令
    从C++到GO
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934443.html
Copyright © 2011-2022 走看看