zoukankan      html  css  js  c++  java
  • 【UOJ 492】单词游戏

    【题目描述】:

    有 N 个盘子,每个盘子上写着一个仅由小写字母组成的英文单词。你需要给这些盘子安排一个合适的顺序,使得相邻两个盘子中,前一个盘子上单词的末字母等于后一个盘子上单词的首字母。请你编写一个程序,判断是否能达到这一要求。如果能,请给出一个合适的顺序。

    【输入描述】:

    多组数据。第一行给出数据组数T,每组数据第一行给出盘子数量N,接下去N行给出小写字母字符串,一种字符串可能出现多次。

    【输出描述】:

    若存在一组合法解输出“Ordering is possible.”,否则输出“The door cannot be opened.”。

    【样例输入】:

    3
    2
    acm
    ibm
    3
    acm
    malform
    mouse
    2
    ok
    ok

    【样例输出】:

    The door cannot be opened.
    Ordering is possible.
    The door cannot be opened.

    【时间限制、数据范围及描述】:

    时间:1s 空间:64M

    1<=N<=10^5;|S|<=1000

    题解:emm并查集+欧拉回路,

    每一个单词有用的信息只有首尾两个字母,那么建一张图令节点表示小写字母;边表示一种单词的转移。问题就变成了在图中判断欧拉路径的存在性。

    若有向图G存在欧拉路径(即为半欧拉图),那么当且仅当G的基图联通且存在顶点u

    的入度比出度大1,v

    的入度比出度小1,其他所有顶点的入度等于出度。

    代码内有些处理细节的精妙之处。

    #include<bits/stdc++.h>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    int t,n,m,c,c1,c2;
    char s[1005];
    int fa[32],u[32],v[32];
    int get(int x)
       { return x==fa[x]?x:fa[x]=get(fa[x]); }
    int main(){
        freopen("492.in","r",stdin);
        freopen("492.out","w",stdout);
        scanf("%d",&t);
        while(t--){
            memset(u,0,sizeof(u));
            memset(v,0,sizeof(v));
            scanf("%d",&n);
            c=c1=c2=0;
            for(int i=1;i<=30;i++)
                fa[i]=i;
            for(int i=1;i<=n;i++){
                scanf("%s",s+1);
                m=strlen(s+1);
                int l=s[1]-'a'+1;
                int r=s[m]-'a'+1;
                fa[get(l)]=get(r);
                u[l]++; v[r]++;
            }
            for(int i=1;i<=26;i++)
                if(((u[i] || v[i]) && (get(i)==i))
                || abs(u[i]-v[i])>1) c++;
            if(c>1){
                puts("The door cannot be opened.");
                continue;
            }
            //连通块和出度入度不相等的个数
            //这是jjj手打的!不是copy的嘤嘤嘤~
            for(int i=1;i<=26;i++){
                if(u[i]>v[i]) c1++;
                if(u[i]<v[i]) c2++;
            }
            if(c1!=c2 || c1>1)
               puts("The door cannot be opened.");
            else
               puts("Ordering is possible.");
            //printf(" ");
        }
        return 0;
    }
  • 相关阅读:
    python可视化---plot()函数
    蜂鸣器的相关知识及简单应用
    将一个文件夹中多个视频的视频帧保存在多个文件夹下
    键盘按键控制程序的简单案例
    Tkinter模块的详细总结
    控制LED灯发光
    python socket 套接字编程 单进程服务器 实现多客户端访问
    python 报错RuntimeError: dictionary changed size during iteration
    HTTP请求行、请求头、请求体详解(转)
    python UDP套接字通信
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11177361.html
Copyright © 2011-2022 走看看