trie树+并查集,蛮好玩
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 #include <list> 9 #include <ctime> 10 #include <set> 11 #include <string.h> 12 #include <queue> 13 #include <cstdio> 14 #define CLR(arr, what) memset(arr, what, sizeof(arr)) 15 typedef long long ll; 16 const int MAX = 510000; 17 using namespace std; 18 19 const int branchNum = 26; //声明常量 20 int colorct; 21 int colorall[MAX]; 22 struct Trie_node { 23 bool isStr; //记录此处是否构成一个串。 24 Trie_node *next[branchNum]; //指向各个子树的指针,下标0-25代表26字符 25 int colornum; 26 Trie_node() : 27 isStr(false) { 28 colornum = 0; 29 for (int i = 0; i < branchNum; i++) 30 next[i] = NULL; 31 } 32 }; 33 34 class Trie { 35 public: 36 Trie(); 37 int insert(const char* word); 38 bool search(char* word); 39 void deleteTrie(Trie_node *root); 40 bool pre_char(bool judge, Trie_node* top); 41 public: 42 Trie_node* root; 43 }; 44 45 Trie::Trie() { 46 root = new Trie_node(); 47 } 48 49 int Trie::insert(const char* word) { 50 Trie_node *location = root; 51 while (*word) { 52 if (location->next[*word - 'a'] == NULL) //不存在则建立 53 { 54 Trie_node *tmp = new Trie_node(); 55 location->next[*word - 'a'] = tmp; 56 } 57 location = location->next[*word - 'a']; //每插入一步,相当于有一个新串经过,指针要向下移动 58 word++; 59 } 60 if (location->colornum == 0) { 61 colorct++; 62 location->colornum = colorct; 63 } 64 colorall[location->colornum]++; 65 location->isStr = true; //到达尾部,标记一个串 66 return location->colornum; 67 } 68 69 bool Trie::search(char *word) { 70 Trie_node *location = root; 71 while (*word && location) { 72 location = location->next[*word - 'a']; 73 word++; 74 } 75 return (location != NULL && location->isStr); 76 } 77 78 void Trie::deleteTrie(Trie_node *root) { 79 int i; 80 for (i = 0; i < branchNum; i++) { 81 if (root->next[i] != NULL) { 82 deleteTrie(root->next[i]); 83 } 84 } 85 delete root; 86 } 87 88 bool Trie::pre_char(bool judge, Trie_node* top) { 89 bool tmpjud, res; 90 res = false; 91 if (top->isStr && judge) 92 return true; 93 tmpjud = judge || top->isStr; 94 for (int i = 0; i < branchNum; i++) { 95 if (top->next[i] != NULL) 96 res = res || pre_char(tmpjud, top->next[i]); 97 } 98 return res; 99 } 100 101 102 int father[MAX], num[MAX]; 103 104 void makeSet(int n) 105 { 106 int i; 107 for(i = 0; i < n; i++) 108 { 109 father[i] = i; //使用本身做根 110 num[i] = 1; 111 } 112 } 113 int findSet(int x) 114 { 115 if(father[x] != x) //合并后的树的根是不变的 116 { 117 father[x] = findSet(father[x]); 118 } 119 return father[x]; 120 } 121 122 void Union(int a, int b) 123 { 124 int x = findSet(a); 125 int y = findSet(b); 126 if(x == y) 127 { 128 return; 129 } 130 if(num[x] <= num[y]) 131 { 132 father[x] = y; 133 num[y] += num[x]; 134 } 135 else 136 { 137 father[y] = x; 138 num[x] += num[y]; 139 } 140 } 141 142 int main() { 143 Trie t; 144 makeSet(MAX); 145 int ca,cb; 146 char c1[11], c2[11]; 147 while (scanf("%s%s", c1, c2) != EOF) { 148 ca=t.insert(c1); 149 cb=t.insert(c2); 150 Union(ca,cb); 151 } 152 if(colorct==0){ 153 cout<<"Possible\n"; 154 return 0; 155 } 156 int cnum=num[findSet(1)]; 157 if(cnum!=colorct){//判断连通性 158 cout<<"Impossible\n"; 159 return 0; 160 } 161 int ct=0; 162 for(int i=0;i<colorct+1;i++){ 163 if(colorall[i]%2==1){ 164 ct++; 165 } 166 if(ct>2){ 167 break; 168 } 169 } 170 if(ct==0||ct==2){ 171 cout<<"Possible\n"; 172 }else{ 173 cout<<("Impossible\n"); 174 } 175 return 0; 176 }