//本来是想练一下欧拉回路的,结果紫书上那题是大水题!!!!!
题意:给出n个单词,是否可以把单词排列成每个单词的第一个字母和上一个单词的最后一个字母相同
解:欧拉通路存在=底图联通+初度!=入度的点至多只有两个(分别为入点和出点)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #include<stack> 11 #include<string> 12 13 using namespace std; 14 15 int T,n; 16 int in[26],out[26]; 17 int f[26]; 18 char s[1007]; 19 20 int gf(int x){ 21 if (x==f[x]) return f[x]; 22 f[x]=gf(f[x]); 23 return f[x]; 24 } 25 26 bool solve(){ 27 memset(in,0,sizeof(in)); 28 memset(out,0,sizeof(out)); 29 for (int i=0;i<26;i++){ 30 f[i]=i; 31 } 32 scanf("%d",&n); 33 for (int i=0;i<n;i++){ 34 scanf("%s",s); 35 int f1=gf(s[0]-‘a‘); 36 int f2=gf(s[strlen(s)-1]-‘a‘); 37 if (f1!=f2){ 38 f[f1]=f2; 39 } 40 in[s[0]-‘a‘]++; 41 out[s[strlen(s)-1]-‘a‘]++; 42 } 43 int pre=-1; 44 for (int i=0;i<26;i++){ 45 if (in[i]!=0 || out[i]!=0){ 46 if (pre==-1) 47 pre=gf(i); 48 else{ 49 if (pre!=gf(i)) return false; 50 pre=gf(i); 51 } 52 } 53 } 54 for (int i=0;i<26;i++){ 55 in[i]=in[i]-out[i]; 56 } 57 sort(in,in+26); 58 for (int i=1;i<25;i++) if (in[i]!=0) return false; 59 if (abs(in[0])>1 || abs(in[25])>1 || in[0]+in[25]!=0) return false; 60 if (in[0]+in[25]!=0) return false; 61 return true; 62 } 63 64 int main(){ 65 scanf("%d",&T); 66 for (int cas=1;cas<=T;cas++){ 67 if (solve()) 68 printf("Ordering is possible.\n"); 69 else 70 printf("The door cannot be opened.\n"); 71 } 72 return 0; 73 } 74 /* 75 3 76 2 77 acm 78 ibm 79 3 80 acm 81 malform 82 mouse 83 2 84 ok 85 ok 86 */
时间: 2024-10-29 00:31:04