【欧拉回路】Play On Words(6-16)
[UVA10129]Play On Words
算法入门经典第6章6-16(P169)
题目大意:有一些单词,问能不能将它们串成字符串(只有前缀和后缀相同才能连)
试题分析:很巧妙的一道题,将每个单词的首尾字符相连,先判断出现过的单词的连通性(并查集),再利用欧拉路有向图的判定方法判定是否构成欧拉路。
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<stack> #include<algorithm> using namespace std; inline int read(){ int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int MAXN=100001; const int INF=999999; int N,M; int T; int fa[27]; int Hash[27]; int root; int find(int x){ if(x!=fa[x]) return fa[x]=find(fa[x]); return x; } void merge(int a,int b){ int x=find(a); int y=find(b); if(x==y) return ; fa[y]=x; root=x; } char str[1001]; int od[27],id[27]; int main(){ T=read(); while(T--){ N=read(); bool flag=false; memset(od,0,sizeof(od)); memset(id,0,sizeof(id)); memset(Hash,false,sizeof(Hash)); for(int i=0;i<=26;i++) fa[i]=i; for(int i=1;i<=N;i++){ scanf("%s",str); int len=strlen(str); merge(str[0]-'a',str[len-1]-'a'); od[str[0]-'a']++; id[str[len-1]-'a']++; Hash[str[len-1]-'a']=Hash[str[0]-'a']=true; } for(int i=0;i<26;i++){ if(Hash[i]&&find(i)!=root) {printf("The door cannot be opened.\n");flag=true;break;} } if(flag) continue; int a=0,b=0; for(int i=0;i<26;i++){ if(abs(od[i]-id[i])>1){ printf("The door cannot be opened.\n"); flag=true; break; } else{ if(od[i]-id[i]==1) a++; else if(id[i]-od[i]==1) b++; } } if(flag) continue; if((!a&&!b)||(a==1&&b==1)){ printf("Ordering is possible.\n"); } else{ printf("The door cannot be opened.\n"); } } }
你——悟到了么?