• UVA-10129 Play on Words (判断欧拉道路的存在性)


    题目大意:给出一系列单词,当某个单词的首字母和前一个单词的尾字母相同,则这两个单词能链接起来。给出一系列单词,问是否能够连起来。

    题目分析:以单词的首尾字母为点,单词为边建立有向图,便是判断图中是否存在欧拉道路。有向图中存在欧拉路径的两个条件是:1、忽略边的方向性后,底图联通;2、奇点个数为0时、奇点个数为2并且满足起点的入度比出度小1和终点的出度比入度大1时,欧拉道路一定存在;

    判断图的连通性有两种方法:1、利用并查集,只判断有几个根节点即可;2、使用DFS,做法实质上就是判断联通块的个数

    利用并查集:

    # include<iostream>
    # include<cstdio>
    # include<map>
    # include<set>
    # include<string>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    int n,in[26],out[26],fa[26],mark[26];
    char p[1005];
    
    int fin(int u)
    {
        int x=u;
        while(fa[u]!=u)
            u=fa[u];
        while(fa[x]!=u){
            int k=fa[x];
            fa[x]=u;
            x=k;
        }
        return u;
    }
    
    int get()
    {
        int cnt=0;
        for(int i=0;i<26;++i)
            if(mark[i]&&fa[i]==i)
                ++cnt;
        return cnt;
    }
    
    bool judge()
    {
        if(get()>1)
            return false;
    
        int cnt=0;
        for(int i=0;i<26;++i)
            if(mark[i]&&in[i]!=out[i])
                ++cnt;
        if(cnt>2)
            return false;
        if(cnt==0)
            return true;
        if(cnt==1)
            return false;
    
        int k1=0,k2=0;
        for(int i=0;i<26;++i){
            if(mark[i]&&in[i]!=out[i]){
                if(in[i]+1==out[i])
                    k1=1;
                if(in[i]==out[i]+1)
                    k2=1;
            }
        }
        return k1&&k2;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            memset(mark,0,sizeof(mark));
            for(int i=0;i<26;++i)  fa[i]=i;
            scanf("%d",&n);
            for(int i=0;i<n;++i){
                scanf("%s",p);
                int l=strlen(p);
                mark[p[0]-'a']=mark[p[l-1]-'a']=1;
                ++out[p[0]-'a'];
                ++in[p[l-1]-'a'];
                int u=fin(p[0]-'a');
                int v=fin(p[l-1]-'a');
                if(u!=v)
                    fa[u]=v;
            }
            if(judge())
                printf("Ordering is possible.
    ");
            else
                printf("The door cannot be opened.
    ");
        }
        return 0;
    }
    

      

    使用DFS:

    # include<iostream>
    # include<cstdio>
    # include<map>
    # include<set>
    # include<string>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    int n,in[26],out[26],mark[26],vis[26],mp[26][26];
    char p[1005];
    
    void dfs(int u)
    {
        for(int i=0;i<26;++i){
            if(mark[i]&&!vis[i]&&mp[u][i]){
                vis[i]=1;
                dfs(i);
            }
        }
    }
    
    bool judge()
    {
        int cnt=0;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<26;++i){
            if(mark[i]&&!vis[i]){
                ++cnt;
                vis[i]=1;
                dfs(i);
            }
        }
        if(cnt>1)
            return false;
    
        for(int i=0;i<26;++i)
            if(mark[i]&&vis[i]==0)
                return false;
    
        cnt=0;
        for(int i=0;i<26;++i)
            if(mark[i]&&in[i]!=out[i])
                ++cnt;
        if(cnt>2)
            return false;
        if(cnt==0)
            return true;
        if(cnt==1)
            return false;
    
        int k1=0,k2=0;
        for(int i=0;i<26;++i){
            if(mark[i]&&in[i]!=out[i]){
                if(in[i]+1==out[i])
                    k1=1;
                if(in[i]==out[i]+1)
                    k2=1;
            }
        }
        return k1&&k2;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            memset(in,0,sizeof(in));
            memset(mp,0,sizeof(mp));
            memset(out,0,sizeof(out));
            memset(mark,0,sizeof(mark));
            scanf("%d",&n);
            for(int i=0;i<n;++i){
                scanf("%s",p);
                int l=strlen(p);
                mp[p[0]-'a'][p[l-1]-'a']=mark[p[0]-'a']=mark[p[l-1]-'a']=1;
                ++out[p[0]-'a'];
                ++in[p[l-1]-'a'];
            }
    
            if(judge())
                printf("Ordering is possible.
    ");
            else
                printf("The door cannot be opened.
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    android 权限大全
    Android限定EditText的输入类型为数字或者英文(包括大小写),EditText,TextView只能输入两位小数
    Android Application 对象介绍
    数据库关键字
    SQLite数据库增删改查操作
    【转】html之<meta> 标签
    javascript剔除数组重复元素的简单方法
    jQuery性能最佳实践
    css学习笔记
    【转】必须避免的html标签十宗罪
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4857641.html
Copyright © 2020-2023  润新知