poj 2337 之 有向图 欧拉路径输出
/*
poj 2337 之 有向图 欧拉路径输出
每个单词看作一条有向边,顶点即为单词首尾字母,然后求欧拉路径即可。
1)为保证字典序,先对单词按字典序排序
2)深搜,输出单词序列
*/
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cstddef> 7 #include <iterator> 8 #include <algorithm> 9 #include <string> 10 #include <locale> 11 #include <cmath> 12 #include <vector> 13 #include <cstring> 14 #include <map> 15 #include <utility> 16 #include <queue> 17 #include <stack> 18 #include <set> 19 #include <functional> 20 using namespace std; 21 typedef pair<int, int> PII; 22 typedef long long int64; 23 const int INF = 0x3f3f3f3f; 24 const int modPrime = 3046721; 25 const double eps = 1e-9; 26 const int MaxN = 1010; 27 const int MaxM = 30; 28 const char Opt[4] = { '+', '-', '*', '/' }; 29 30 int n; 31 32 struct Edge 33 { 34 int to; 35 int nextEdge; 36 int index; 37 bool isVisited; 38 }; 39 Edge edge[MaxN]; 40 int head[MaxM]; 41 42 int startPot = INF; 43 int in[MaxM]; 44 int out[MaxM]; 45 vector<string> wordVec; 46 vector<int> eulerPath; 47 48 int total = 0; 49 50 51 //Union-Find Sets 52 int ftr[MaxM]; 53 int rnk[MaxM]; 54 void ufsIni() 55 { 56 for (int i = 0; i < MaxM; ++i) 57 { 58 ftr[i] = i; 59 rnk[i] = 0; 60 } 61 } 62 int ufsFind(int x) 63 { 64 if (x == ftr[x]) return x; 65 return ftr[x] = ufsFind(ftr[x]); 66 } 67 void ufsUnite(int x, int y) 68 { 69 x = ufsFind(x); 70 y = ufsFind(y); 71 if (x == y) return; 72 73 if (rnk[x] > rnk[y]) 74 { 75 ftr[y] = x; 76 } 77 else 78 { 79 ftr[x] = y; 80 if (rnk[x] == rnk[y]) 81 { 82 ++rnk[y]; 83 } 84 } 85 } 86 87 void addEdge(int u, int v, int index) 88 { 89 edge[total].to = v; 90 edge[total].index = index; 91 edge[total].nextEdge = head[u]; 92 edge[total].isVisited = false; 93 head[u] = total++; 94 } 95 96 97 bool isExistEulerpath(int n) 98 { 99 100 ufsIni(); 101 for (int i = 0; i < n; ++i) 102 { 103 string word; 104 cin >> word; 105 wordVec.push_back(word); 106 } 107 sort(wordVec.begin(), wordVec.end(), greater<string>()); 108 set<int> potSet; 109 for (int i = 0; i < n; ++i) 110 { 111 string word = wordVec[i]; 112 int fromCh = word[0] - 'a', toCh = word[word.size() - 1] - 'a'; 113 ++out[fromCh]; 114 ++in[toCh]; 115 addEdge(fromCh, toCh, i); 116 potSet.insert(fromCh); 117 potSet.insert(toCh); 118 startPot = min(startPot, min(fromCh, toCh)); 119 ufsUnite(fromCh, toCh); 120 } 121 for (set<int>::iterator it = potSet.begin(); it != potSet.end(); ++it) 122 { 123 if (ufsFind(ftr[*it]) != ufsFind(ftr[*(potSet.begin())])) 124 { 125 return false; 126 } 127 } 128 int tmpU = 0, tmpV = 0; 129 for (set<int>::iterator it = potSet.begin(); it != potSet.end(); ++it) 130 { 131 if (out[*it] - in[*it] == 1) 132 { 133 ++tmpU; 134 if (tmpU > 1) 135 { 136 return false; 137 } 138 startPot = *it; 139 } 140 else 141 { 142 if (out[*it] - in[*it] == -1) 143 { 144 ++tmpV; 145 if (tmpV > 1) 146 { 147 return false; 148 } 149 } 150 else 151 { 152 if (out[*it] - in[*it] != 0) 153 { 154 return false; 155 } 156 } 157 } 158 } 159 if (!((0 == tmpU && 0 == tmpV) || (1 == tmpU && 1 == tmpV))) 160 { 161 return false; 162 } 163 return true; 164 } 165 166 167 void Solve(int pos) 168 { 169 for (int i = head[pos]; i != -1; i = edge[i].nextEdge) 170 { 171 if (!edge[i].isVisited) 172 { 173 edge[i].isVisited = true; 174 Solve(edge[i].to); 175 eulerPath.push_back(edge[i].index); 176 } 177 } 178 } 179 180 int main() 181 { 182 #ifdef HOME 183 freopen("in", "r", stdin); 184 //freopen("out", "w", stdout); 185 #endif 186 187 int T; 188 cin >> T; 189 while (T--) 190 { 191 startPot = INF; 192 total = 0; 193 fill(head, head + MaxM, -1); 194 fill(in, in + MaxM, 0); 195 fill(out, out + MaxM, 0); 196 cin >> n; 197 if (isExistEulerpath(n)) 198 { 199 Solve(startPot); 200 for (vector<int>::reverse_iterator rIt = eulerPath.rbegin(); rIt != eulerPath.rend(); ++rIt) 201 { 202 cout << wordVec[*rIt]; 203 if (rIt != eulerPath.rend() - 1) 204 { 205 cout << "."; 206 } 207 else 208 { 209 cout << endl; 210 } 211 } 212 } 213 else 214 { 215 cout << "***" << endl; 216 } 217 wordVec.clear(); 218 eulerPath.clear(); 219 } 220 221 222 #ifdef HOME 223 cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl; 224 _CrtDumpMemoryLeaks(); 225 #endif 226 return 0; 227 }