您的位置:首页 > 其它

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;
}








                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: