HDU ACM 1116 Play on Words(并查集 + 欧拉图)
http://acm.hdu.edu.cn/showproblem.php?pid=1116
题意:给出N个字符串,若所以字符串能连成一串则输出Ordering is possible.否则输出The door cannot be opened.
非常蛋疼的用了并查集.
思路是用并查集找出所有字符串能不能形成一个集合(只有一个几个 + 用欧拉图的特性判断能不能把所有的点连成一线
判断欧拉图: 欧拉回路:所有点的入度等于出度.
欧拉通路:有且仅有两个点的入度不等于出度且入度与出度相差1.(注意:判断时相差2的不能忽略,也要进行记录)
View Code
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 const int MAX = 30 + 10; 6 int father[MAX]; 7 int rank1[MAX]; 8 int sign[MAX]; 9 10 void Make_Set(int x)//初始化 11 { 12 father[x] = x; 13 rank1[x] = 0; 14 } 15 16 int Find_Set(int x)//找根节点 17 { 18 int i=0; 19 while(father[x] != x) 20 { 21 sign[i++] = x; 22 x = father[x]; 23 } 24 for(i;i>=1;i--) 25 { 26 father[sign[i-1]] = x; 27 } 28 return x; 29 } 30 31 32 void Union(int x,int y)//合并 33 { 34 x = Find_Set(x); 35 y = Find_Set(y); 36 if(x == y) 37 { 38 return; 39 } 40 if(rank1[x] > rank1[y]) 41 { 42 father[y] = x; 43 } 44 else if(rank1[x] < rank1[y]) 45 { 46 father[x] = y; 47 } 48 else if(rank1[x] ==rank1[y]) 49 { 50 father[x] = y; 51 rank1[y]++; 52 } 53 } 54 55 int main() 56 { 57 int used[MAX]; 58 int in[MAX] ; 59 int out[MAX]; 60 int T; 61 cin>>T; 62 while(T--) 63 { 64 memset(used, 0, sizeof(used)); 65 memset(in, 0 ,sizeof(used)); 66 memset(out, 0 ,sizeof(used)); 67 68 int n; 69 cin>>n; 70 int i; 71 for(i=0;i<MAX-1;i++) 72 { 73 Make_Set(i); 74 } 75 for(i=0;i<n;i++) 76 { 77 char str[1100]; 78 cin>>str; 79 used[str[0] - 'a'] = 1; 80 used[str[strlen(str)-1] - 'a'] = 1; 81 Union(str[0] - 'a',str[strlen(str)-1] - 'a'); 82 out[str[0] - 'a']++; 83 in[str[strlen(str)-1] - 'a']++; 84 } 85 int sum = 0; 86 int mark = 0; 87 int mark1 = 0; 88 int mark2 = 0; 89 int mark3 = 0; 90 int num = 0; 91 for(i=0;i<MAX-1;i++) 92 { 93 if(used[i]) 94 { 95 num++; 96 } 97 if(used[i] && father[i] == i) 98 { 99 sum++; 100 } 101 102 103 if (used[i] && in[i] != out[i] ) 104 { 105 if(used[i] && in[i] - out[i] == 1) 106 { 107 mark1++; 108 } 109 else if(used[i] && out[i] - in[i] == 1) 110 { 111 mark2++; 112 } 113 else 114 { 115 mark=1; 116 } 117 118 } 119 else if (used[i] && in[i] == out[i]) 120 { 121 mark3++; 122 } 123 } 124 125 126 if (mark) 127 { 128 cout<<"The door cannot be opened."<<endl; 129 } 130 else 131 if(sum == 1 && ((mark1 == 1 && mark2 == 1) || mark3 == num) ) 132 { 133 cout<<"Ordering is possible."<<endl; 134 } 135 else 136 { 137 cout<<"The door cannot be opened."<<endl; 138 } 139 140 141 } 142 143 return 0; 144 }