UVA

2.解题思路:本题利用欧拉回路存在条件解决。可以将所有的单词看做边,26个字母看做端点,那么本题其实就是问是否存在一条路径,可以到达所有出现过的字符端点。由于本题还要求了两个单词拼在一起的条件是前一个单词的右端点和本单词的左端点一样。所以这是一个有向图。根据结论:有向图的底图(忽略边的方向后的图)必须连通;有向图中最多只能有两个端点的入度不等于出度,且必须是其中一点的入度比出度小1,另一点的入度比出度大1。因此先判断端点是否都连通,再判断每个端点的度数是否满足结论即可。

那么,如何判断连通性呢?第一种方法是利用DFS,第二种方法可以利用并查集。本题利用并查集来判断是否连通。

  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.
");
 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.
");
 91     }
 92     else{
 93         printf("The door cannot be opened.
");
 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 }
View Code
原文地址:https://www.cnblogs.com/UniqueColor/p/4839773.html