LOJ#10106. 「一本通 3.7 例 2」单词游戏
题目链接: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≤105,∣S∣≤1000
题解:
一道xjb判NO的欧拉路径好题。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> int t,n,m; char s[1035]; int fa[35],u[35],v[35],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,0,sizeof u); memset(v,0,sizeof v); scanf("%d",&n); cnt=cnt1=cnt2=0; for(int i=1;i<=35;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,r=s[m]-'a'+1; fa[find(l)]=find(r),u[l]++,v[r]++; } for(int i=1;i<=26;i++) if(((u[i]||v[i]) && (find(i)==i)) || abs(u[i]-v[i])>1) cnt++; if(cnt>1) { printf("The door cannot be opened.\n"); continue; } for(int i=1;i<=26;i++) if(u[i]>v[i]) cnt1++; else if(u[i]<v[i]) cnt2++; if(cnt1!=cnt2 || cnt1>1) { printf("The door cannot be opened.\n"); continue; } printf("Ordering is possible.\n"); } }