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 }
 
 

 

 
 
 

 

 

你可能感兴趣的:(poj 2337 之 有向图 欧拉路径输出)