const int MAXN = 1100; string ipt[MAXN]; int cmp(string a, string b) { return a < b; } //集合中可以有很多元素(没用到的也行) //下标从零开始 //但是在函数isEulerRoad的第一个参数必须是前n个有用的点 //方便自己加一些点,而且不影响判断连通性 struct Direct_Euler { int out[MAXN], father[MAXN]; vector<int> vt[MAXN]; stack<int> sk; typedef pair<int, int> pii; set<pii> st; void init() { st.clear(); while (!sk.empty()) sk.pop(); REP(i, MAXN) { father[i] = i; vt[i].clear(); } CLR(out, 0); } int find(int n) { return father[n] == n ? n : father[n] = find(father[n]); } bool isOne(int n) { int t = find(0); REP(i, n) { if (find(i) != t) return false; } return true; } void merge(int a, int b) { vt[a].push_back(b); out[a]++; out[b]--; int fa = find(a), fb = find(b); father[fb] = fa; } // n:判断前n个点是否是一个集合(并查集使用) //是返回true,而且如果是欧拉回路circle = 0,如果是欧拉路circle > 0 //不是返回false bool isEulerRoad(int n, int& tot, int& ind) { if (!isOne(n)) return false; int end = 0, same = 0; REP(i, MAXN) { if (out[i] == 1) ++tot, ind = i; else if (out[i] == -1) end++; else if (out[i] == 0) same++; } return (tot + end + same == MAXN && tot <= 1); } //搜索路径,结果保留在sk中 void solve(int n) { REP(i, vt[n].size()) { int next = vt[n][i]; if (!st.count(MP(n, next))) { st.insert(MP(n, next)); solve(next); } } sk.push(n); } //输出路径,自己写格式 void display() { int cnt = 0; vector<string> vt; while (!sk.empty()) { int t = sk.top(); if (t < 1000) { if (cnt != 0) putchar(‘.‘); cout << ipt[t]; cnt++; } sk.pop(); } cout << endl; } } graph; int main() { // freopen("in.txt", "r", stdin); int n, ncase; RI(ncase); while (ncase--) { graph.init(); RI(n); REP(i, n) cin >> ipt[i]; sort(ipt, ipt + n, cmp); REP(i, n) { graph.merge(ipt[i][0] - ‘a‘ + 1000, i); graph.merge(i, ipt[i][ipt[i].size() - 1] - ‘a‘ + 1000); } int ind = ipt[0][0] - ‘a‘ + 1000, tot = 0; if (graph.isEulerRoad(n, tot, ind)) { graph.solve(ind); graph.display(); } else puts("***"); } return 0; }
原文:http://blog.csdn.net/wty__/article/details/21535739