判断是欧拉通路后,DFS简单剪枝求解字典序最小的欧拉通路路径
//Time:16Ms Memory:228K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std; #define MAX 1005
#define MAXS 24 //姓名
#define MAXN 26 //字母 struct Edge{
char name[MAXS];
int a,b;
friend bool operator < (Edge &e1, Edge &e2)
{ return strcmp(e1.name, e2.name) < 0; }
}e[MAX]; int n;
int in[MAXN], out[MAXN]; //入度与出度
int order[MAX]; //顺序路径
bool v[MAX]; bool dfs(int x, int rk)
{
if(rk == n) return true;
for(int i = 0; i < n; i++)
{
if(!v[i] && x == e[i].a){
v[i] = true;
order[rk] = i;
if(dfs(e[i].b, rk+1)) return true;
v[i] = false;
}
}
return false;
} int main()
{
//freopen("in.txt","r",stdin); int T;
scanf("%d",&T);
while(T--){
memset(e,0,sizeof(e));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(order,-1,sizeof(order));
memset(v,false,sizeof(v));
scanf("%d",&n);
//构图
int st = 26; //st:起点
for(int i = 0; i < n; i++)
{
scanf("%s",e[i].name);
e[i].a = e[i].name[0] - 'a';
e[i].b = e[i].name[strlen(e[i].name) - 1] - 'a';
out[e[i].a]++;
in[e[i].b]++;
if(e[i].a < st) st = e[i].a;
}
sort(e,e+n);
//欧拉路判定
int odd = 0; //奇度结点个数
bool flag = true;
for(int i = 0 ; i < MAXN; i++)
{
if(in[i] != out[i])
{
odd++;
if(out[i] - in[i] == 1)
st = i;
else if(out[i] - in[i] != -1)
{
flag = false;
break;
}
}
}
if(flag && (odd ==2 || odd == 0) && dfs(st,0)) //满足欧拉通路(排除非连通)+完整路径(判断非连通)
{
for(int i = 0; i < n - 1; i++)
printf("%s.", e[order[i]].name);
printf("%s\n", e[order[n-1]].name);
}
else printf("***\n"); } return 0;
}