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 }

 

 
时间: 2024-10-23 10:24:08

poj 2337 之 有向图 欧拉路径输出的相关文章

POJ 2337 Catenyms (有向图欧拉通路)

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9914   Accepted: 2588 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For e

poj 2337 Catenyms 【欧拉路径】

题目链接:http://poj.org/problem?id=2337 题意:给定一些单词,假设一个单词的尾字母与还有一个的首字母同样则能够连接.问能否够每一个单词用一次,将全部单词连接,能够则输出字典序最小的序列. 代码: (bin 神的板子) #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include

poj 2337 欧拉回路按照最小字典序输出+注意为了按最小字典序怎么处理邻接表

http://poj.org/problem?id=2337 WA了好久,昨晚1点多睡不着写的,狂WA,当时是因为用邻接矩阵存储,比如aba,aa只能存下一个,这个之前还没遇到过,今天才注意到--邻接矩阵无法存储平行边, 关于欧拉回路判断看我另几篇日志或者看我的欧拉总结 再贴个输出欧拉回路的模板 其中,参数u是起点,注意如果是输出欧拉路径的话,u必须是出度比入度大一的那个点,如果输出欧拉回路,随便按要求找个就行 void euler(int u) { for(int i=head[u];i!=-

POJ 2337 Catenyms (欧拉回路+并查集)

题目地址:POJ 2337 这题跟POJ 1386差不多,只不过这题多一个输出路径而已. 按字母来建边,每个单词的首字母和尾字母加边.先判断是否连通,然后判断每个字母的入度和出度不能出现差的绝对值大于2,然后入度和出度差的绝对值为1的不能超过两个.就可以形成欧拉路径 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <alg

poj 1815 Friendship 最小割输出最小方案

这题卡了好久啊,最小割模型很容易想,拆点就行.就像poj的Thieves一样 每个点 a拆成 a->a',容量为1. 其他相连的点 a'->b ,容量为INF 源连接s',t连接汇 问题在于输出最小的割集 更好的方法我还不会,只能枚举. 这里基于贪心的思想,从小到大删边, 若删除i->i',会使得最小割变小,则输出i,并且i->i'这条边不要恢复 若最小割不变,则恢复这条边,继续枚举. 一开始就是因为恢复了要割去的边,无限WA. #include<cstdio> #in

poj 2594Treasure Exploration(有向图路径可相交的最小路径覆盖)

1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #define N 505 6 using namespace std; 7 8 int g[N][N]; 9 int n, m; 10 int vis[N], linker[N]; 11 bool dfs(int u){ 12 for(int i=1; i<=n; ++i) 13 if

poj 2337 有向图输出欧拉路径

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10186   Accepted: 2650 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For

POJ 2337 &amp;&amp; ZOJ 1919--Catenyms 【有向图 &amp;&amp; 欧拉路判断 &amp;&amp; 欧拉路径】

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10427   Accepted: 2726 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For

poj 1386 Play on Words 有向图欧拉路径判断

题意: 给n个单词,问是否可以将他们排成一排,使得前一个单词的末字符和后一个单词的首字符相同. 分析: 把每个单词看成一条边,转化为有向图是否存在欧拉路径问题. 代码: //poj 1386 //sep9 #include <iostream> #include <vector> #include <algorithm> #include <map> #include <string> using namespace std; const int