把单词的第一个字母和最后一个字母作为点,由第一个字母向最后一个字母连一条有向边, 问题转化为判断一个有向图是否存在欧拉道路 有向图存在欧拉道路的条件: 在忽略边的方向后,图必须是连通的,同时最多只能有两个点的入度不等于出度, 而且必须是其中一个点的出度刚好比入度大1(把它作为起点),另一个的入度比出度大1(把它作为终点).
代码:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int N= 27; 6 int in[N], out[N],use[N], set[N]; 7 int find( int x) 8 { 9 int r=x; 10 if(r!= set[r]) 11 r= set[r]; 12 return r; 13 } 14 void merge( int x, int y) 15 { 16 int fx=find(x); 17 int fy=find(y); 18 if(fx!=fy) 19 { 20 set[fy]=fx; 21 } 22 } 23 int main() 24 { 25 int i,j,t,n,cnt1,cnt2,cnt3,flag; 26 char s[ 1001]; 27 scanf( " %d ",&t); 28 while(t--) 29 { 30 scanf( " %d ",&n); 31 memset( in, 0, sizeof( in)); 32 memset( out, 0, sizeof( out)); 33 memset(use, 0, sizeof(use)); 34 for(i= 0;i<= 26;i++) 35 set[i]=i; 36 while(n--) 37 { 38 scanf( " %s ",&s); 39 i=s[ 0]- ' a '; 40 j=s[strlen(s)- 1]- ' a '; 41 use[i]=use[j]= 1; 42 in[j]++; 43 out[i]++; 44 merge(i,j); 45 } 46 cnt1= 0,cnt2= 0,cnt3= 0; 47 flag= 1; 48 for(i= 0;i< 26;i++) 49 { 50 if(use[i]) 51 { 52 if( set[i]==i) 53 cnt1++; 54 if( in[i]!= out[i]) 55 { 56 if( in[i]- out[i]== 1) 57 cnt2++; 58 else if( out[i]- in[i]== 1) 59 cnt3++; 60 else 61 flag= 0; 62 } 63 } 64 } 65 if((cnt1== 1&&flag&&cnt2== 0&&cnt3== 0)||(cnt1== 1&&flag&&cnt2== 1&&cnt3== 1)) 66 puts( " Ordering is possible. "); 67 else 68 puts( " The door cannot be opened. "); 69 } 70 return 0; 71 }