poj 2337 之 有向图 欧拉路径输出
2016-01-06 01:09
375 查看
/* poj 2337 之 有向图 欧拉路径输出 每个单词看作一条有向边,顶点即为单词首尾字母,然后求欧拉路径即可。 1)为保证字典序,先对单词按字典序排序 2)深搜,输出单词序列 */
#include <iostream> #include <fstream> #include <sstream> #include <cstdlib> #include <cstdio> #include <cstddef> #include <iterator> #include <algorithm> #include <string> #include <locale> #include <cmath> #include <vector> #include <cstring> #include <map> #include <utility> #include <queue> #include <stack> #include <set> #include <functional> using namespace std; typedef pair<int, int> PII; typedef long long int64; const int INF = 0x3f3f3f3f; const int modPrime = 3046721; const double eps = 1e-9; const int MaxN = 1010; const int MaxM = 30; const char Opt[4] = { '+', '-', '*', '/' }; int n; struct Edge { int to; int nextEdge; int index; bool isVisited; }; Edge edge[MaxN]; int head[MaxM]; int startPot = INF; int in[MaxM]; int out[MaxM]; vector<string> wordVec; vector<int> eulerPath; int total = 0; //Union-Find Sets int ftr[MaxM]; int rnk[MaxM]; void ufsIni() { for (int i = 0; i < MaxM; ++i) { ftr[i] = i; rnk[i] = 0; } } int ufsFind(int x) { if (x == ftr[x]) return x; return ftr[x] = ufsFind(ftr[x]); } void ufsUnite(int x, int y) { x = ufsFind(x); y = ufsFind(y); if (x == y) return; if (rnk[x] > rnk[y]) { ftr[y] = x; } else { ftr[x] = y; if (rnk[x] == rnk[y]) { ++rnk[y]; } } } void addEdge(int u, int v, int index) { edge[total].to = v; edge[total].index = index; edge[total].nextEdge = head[u]; edge[total].isVisited = false; head[u] = total++; } bool isExistEulerpath(int n) { ufsIni(); for (int i = 0; i < n; ++i) { string word; cin >> word; wordVec.push_back(word); } sort(wordVec.begin(), wordVec.end(), greater<string>()); set<int> potSet; for (int i = 0; i < n; ++i) { string word = wordVec[i]; int fromCh = word[0] - 'a', toCh = word[word.size() - 1] - 'a'; ++out[fromCh]; ++in[toCh]; addEdge(fromCh, toCh, i); potSet.insert(fromCh); potSet.insert(toCh); startPot = min(startPot, min(fromCh, toCh)); ufsUnite(fromCh, toCh); } for (set<int>::iterator it = potSet.begin(); it != potSet.end(); ++it) { if (ufsFind(ftr[*it]) != ufsFind(ftr[*(potSet.begin())])) { return false; } } int tmpU = 0, tmpV = 0; for (set<int>::iterator it = potSet.begin(); it != potSet.end(); ++it) { if (out[*it] - in[*it] == 1) { ++tmpU; if (tmpU > 1) { return false; } startPot = *it; } else { if (out[*it] - in[*it] == -1) { ++tmpV; if (tmpV > 1) { return false; } } else { if (out[*it] - in[*it] != 0) { return false; } } } } if (!((0 == tmpU && 0 == tmpV) || (1 == tmpU && 1 == tmpV))) { return false; } return true; } void Solve(int pos) { for (int i = head[pos]; i != -1; i = edge[i].nextEdge) { if (!edge[i].isVisited) { edge[i].isVisited = true; Solve(edge[i].to); eulerPath.push_back(edge[i].index); } } } int main() { #ifdef HOME freopen("in", "r", stdin); //freopen("out", "w", stdout); #endif int T; cin >> T; while (T--) { startPot = INF; total = 0; fill(head, head + MaxM, -1); fill(in, in + MaxM, 0); fill(out, out + MaxM, 0); cin >> n; if (isExistEulerpath(n)) { Solve(startPot); for (vector<int>::reverse_iterator rIt = eulerPath.rbegin(); rIt != eulerPath.rend(); ++rIt) { cout << wordVec[*rIt]; if (rIt != eulerPath.rend() - 1) { cout << "."; } else { cout << endl; } } } else { cout << "***" << endl; } wordVec.clear(); eulerPath.clear(); } #ifdef HOME cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl; _CrtDumpMemoryLeaks(); #endif return 0; }
相关文章推荐
- 将无序数列升序排列,并输出排列结果和排列后的下标
- [看书日记20160106]Activity的Flags , IntentFilter ,Android的消息机制
- HDU 1177."Accepted today?"【结构体排序(水)】【1月6】
- How MapReduce Works
- 静态分配和动态分配内存的区别
- IP学习
- Linux系统密钥验证(附件有实验过程和截图)
- windows 运行命令大全
- Android退出应用最优雅的方式(改进版)
- 转载的一篇关于vld的文章
- 2015年12月工作总结
- 远程链接服务器工具的使用
- linux看视频黑屏和无法调节屏幕亮度
- QStringLiteral的两篇外文解释(编译期转换成QString)
- hadoop集群搭建【伪分布式】
- 数据结构 JAVA描述(十五) 动态查找表 二叉排序树 二叉平衡树
- BigDecimal的学习
- QtInternal 之 高效使用QString(使用QLatin1String,QStringRef,QStringBuilder,QStringMatcher等相关类)
- C# 检查进程是否已经启动
- Arch Linux安装