LOJ#10106. 「一本通 3.7 例 2」单词游戏

时间:2022-10-26 20:29:46

题目链接:https://loj.ac/problem/10106

题目描述

来自 ICPC CERC 1999/2000,有改动。

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

输入格式

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

输出格式

若存在一组合法解输出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.

数据范围与提示

1≤N≤105,∣S∣≤10001 \le N \le 10^5,|S| \le 10001≤N≤10​5​​,∣S∣≤1000

题解:

一道xjb判NO的欧拉路径好题。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
int t,n,m;
char s[];
int fa[],u[],v[],cnt,cnt1,cnt2;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main()
{
scanf("%d",&t);
while (t--)
{
memset(u,,sizeof u);
memset(v,,sizeof v);
scanf("%d",&n);
cnt=cnt1=cnt2=;
for(int i=;i<=;i++) fa[i]=i;
for(int i=;i<=n;i++)
{
scanf("%s",s+),m=strlen(s+);
int l=s[]-'a'+,r=s[m]-'a'+;
fa[find(l)]=find(r),u[l]++,v[r]++;
}
for(int i=;i<=;i++)
if(((u[i]||v[i]) && (find(i)==i)) || abs(u[i]-v[i])>) cnt++;
if(cnt>)
{
printf("The door cannot be opened.\n");
continue;
}
for(int i=;i<=;i++)
if(u[i]>v[i]) cnt1++;
else if(u[i]<v[i]) cnt2++;
if(cnt1!=cnt2 || cnt1>)
{
printf("The door cannot be opened.\n");
continue;
}
printf("Ordering is possible.\n");
}
}