我的代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxm = 26;
const int maxn = 1010;
struct node
{
int to,ord;
string word;
};
static int n;
static int top[maxm] = {0}; // 图的节点,至多26个
static int treeset[maxm]; // 基图(无向图),并查集 判断是否联通
static int outd[maxm],ind[maxm]; // 出度、入度
static string s[maxn];
static int vis[maxn];
static string res[maxn];
static vector<node> Edge[maxm];
// 并查集查找根节点(压缩路径)
int tfind(int x){
return treeset[x]==x ? x : treeset[x] = tfind(treeset[x]);
}
// 深搜,st表示词链中有几个单词,now表示现在到达了哪一个点
// pre_edge表示上一条边的序号,方便回溯
void dfs(int st,int now,int pre_edge)
{
if(st==n)//如果到达终点
{
for(int i=1;i<=n;i++)//输出结果
{
cout << res[i];
if (i < n)
cout << ".";
}
exit(0);
}
for(int k=0;k<Edge[now].size();k++)
{
if(!vis[Edge[now][k].ord])//如果未被标记过
{
vis[Edge[now][k].ord]=1;
res[st+1]=Edge[now][k].word;
dfs(st+1,Edge[now][k].to,Edge[now][k].ord);
}
}
vis[pre_edge]=0;//回溯
return;
}
int main() {
cin >> n;
for (int i = 0; i < maxm; i++) { // 并查集,预置每个节点的父节点是自己
treeset[i] = i;
}
for (int i = 0; i < n; i++) {
cin >> s[i];
}
sort(s, s + n); //排序
for (int i = 0; i < n; i++) { // 建图
int h = s[i][0]-'a'; // 首字母
int t = s[i][s[i].length()-1]-'a'; // 末字母
top[h]++; // 无向图度
top[t]++;
outd[h]++; // 有向图出度
ind[t]++; // 有向图入度
int root_h = tfind(h);
int root_t = tfind(t);
if (root_h != root_t) { // 并集
treeset[root_h] = root_t;
}
node tmp;//新建一条边
tmp.to=t;
tmp.ord=i;
tmp.word=s[i];
Edge[h].push_back(tmp); //vector存图
}
int set_count = 0;
int set_count_root = -1;
int startpoint = -1, endpoint = -1;
int totalpoint = 0, dpoint = 0, spoint = 0;
// 并查集判断基图联通,顺便判断欧拉迹/闭迹
for(int var = 0; var < maxm; var++){
if (top[var] != 0) {
totalpoint++;
if(tfind(var) != set_count_root) {
set_count++;
set_count_root = tfind(var);
if (set_count > 1) { // 多个集合,图不连通
cout << "***";
return 0;
}
}
if (top[var]%2 == 0)
spoint++;
else {
dpoint++;
// 欧拉通路(可能)起点
if (outd[var] == ind[var] + 1) {
startpoint = var;
}
// 欧拉通路(可能)终点
if (ind[var] == outd[var] + 1) {
endpoint = var;
}
}
}
}
if (dpoint == 2) {
// 两个奇数度顶点,是欧拉通路
dfs(0,startpoint,0);
} else if(totalpoint == spoint){
// 所有顶点都是偶数度,是欧拉回路
dfs(0,0,0);
} else {
// 多个简单通路,不符合题意
cout << "***";
return 0;
}
return 0;
}