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

本题直接将每个单词的首字母和尾字母连一条有向边,然后判断是否存在欧拉路径即可。

Code:
#include<bits/stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
using namespace std;
inline void read(int &x){
    char ch=getchar(),c=ch;
    x=0;
    while(ch<'0' || ch>'9'){
         c=ch;
         ch=getchar();
    }
    while(ch>='0' && ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    if(c=='-')x=-x;
} 


char s[1001];
int t,n,m,i,a,b,c,l,r;
int fa[50],u[50],v[50];
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main(){
    read(t);
    while(t--){
        memset(u,0,sizeof u);
        memset(v,0,sizeof v);
        read(n);
        a=b=c=0;
        for(i=1;i<=30;i++)fa[i]=i;
        for(i=1;i<=n;i++){
            scanf("%s",s+1);
            m=strlen(s+1);
            l=s[1]-'a'+1;
            r=s[m]-'a'+1;
            fa[find(l)]=find(r);
            u[l]++;
            v[r]++;
        }
        for(i=1;i<=26;i++)if(((u[i]||v[i])&&(find(i)==i))||u[i]-v[i]>1||u[i]-v[i]<-1)a++;
        if(a>1){
            puts("The door cannot be opened.");
            continue;
    }
        for(i=1;i<=26;i++)
            if(u[i]>v[i])b++;
            else if(u[i]<v[i]){
                c++;
            }
        if(b!=c||b>1){
            puts("The door cannot be opened.");
            continue;
        }
        puts("Ordering is possible.");
    }
    return 0;
}

转载于:https://www.cnblogs.com/ukcxrtjr/p/11188463.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值