UVA - 10129 Play on Words(欧拉回路+并查集)
2.解题思路:本题利用欧拉回路存在条件解决。可以将所有的单词看做边,26个字母看做端点,那么本题其实就是问是否存在一条路径,可以到达所有出现过的字符端点。由于本题还要求了两个单词拼在一起的条件是前一个单词的右端点和本单词的左端点一样。所以这是一个有向图。根据结论:有向图的底图(忽略边的方向后的图)必须连通;有向图中最多只能有两个端点的入度不等于出度,且必须是其中一点的入度比出度小1,另一点的入度比出度大1。因此先判断端点是否都连通,再判断每个端点的度数是否满足结论即可。
那么,如何判断连通性呢?第一种方法是利用DFS,第二种方法可以利用并查集。本题利用并查集来判断是否连通。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<math.h> 7 #include<algorithm> 8 #include<queue> 9 #include<set> 10 #include<bitset> 11 #include<map> 12 #include<vector> 13 #include<stdlib.h> 14 #include <stack> 15 using namespace std; 16 int dirx[]={0,0,-1,1}; 17 int diry[]={-1,1,0,0}; 18 #define PI acos(-1.0) 19 #define max(a,b) (a) > (b) ? (a) : (b) 20 #define min(a,b) (a) < (b) ? (a) : (b) 21 #define ll long long 22 #define eps 1e-10 23 #define MOD 1000000007 24 #define N 100006 25 #define inf 1e12 26 int n; 27 int u[N],v[N]; 28 int in[N],out[N]; 29 int vis[N]; 30 int fa[N]; 31 int num; 32 void init(){ 33 memset(in,0,sizeof(in)); 34 memset(out,0,sizeof(out)); 35 memset(vis,0,sizeof(vis)); 36 for(int i=0;i<N;i++){ 37 fa[i]=i; 38 } 39 num=0; 40 } 41 ///////////////////////////////////////////////////////////////////// 42 int find(int x){ 43 return fa[x]==x?x:fa[x]=find(fa[x]); 44 } 45 void merge(int x,int y){ 46 int root1=find(x); 47 int root2=find(y); 48 if(root1==root2) return; 49 fa[root1]=root2; 50 } 51 ////////////////////////////////////////////////////////////////////// 52 void solve(){ 53 54 for(int i=0;i<n;i++){ 55 merge(u[i],v[i]); 56 } 57 int i=0; 58 for(i;!vis[i];i++); 59 60 int x=find(i);//判断能否连通 61 for(int j=i+1;j<26;j++){ 62 if(vis[j]){ 63 int y=find(j); 64 if(x!=y){ 65 printf("The door cannot be opened.\n"); 66 return; 67 } 68 } 69 } 70 71 int flag=1; 72 int cnt=0; 73 for(int i=0;i<26;i++){ 74 if(vis[i]){ 75 if(in[i]!=out[i]){ 76 if(in[i]==out[i]-1) cnt++; 77 else if(in[i]==out[i]+1) cnt++; 78 else{ 79 flag=0; 80 break; 81 } 82 } 83 if(cnt>2){ 84 flag=0; 85 break; 86 } 87 } 88 } 89 if(flag){ 90 printf("Ordering is possible.\n"); 91 } 92 else{ 93 printf("The door cannot be opened.\n"); 94 } 95 96 } 97 int main() 98 { 99 int t; 100 scanf("%d",&t); 101 while(t--){ 102 103 init(); 104 105 char s[1006]; 106 scanf("%d",&n); 107 for(int i=0;i<n;i++){ 108 scanf("%s",s); 109 int len=strlen(s); 110 int a=s[0]-'a'; 111 int b=s[len-1]-'a'; 112 u[i]=a,v[i]=b; 113 in[a]++,out[b]++; 114 vis[a]=1; 115 vis[b]=1; 116 } 117 solve(); 118 } 119 return 0; 120 }