给出几个单词,问你是否能首位相接起来,按照字典的升序进行排序
先根据入度出度判断是否能形成欧拉路,否则就不能形成
然后再进行DFs搜索
需要注意一点的是,在判断欧拉路找起始点的时候,有可能会形成欧拉回路,因此找到此时的最小的一个节点即可

1 #define N 1005
2 #include<algorithm>
3 #include<iostream>
4 using namespace std;
5 int n;
6 int degree_in[30],degree_out[30],edge_order[1000];
7 struct Edge
8 {
9 int st,en;
10 char str[30];
11 };
12 Edge edge[1000];
13 bool used[1000];
14 bool cmp(Edge a,Edge b)
15 {
16 return strcmp(a.str,b.str)<0;
17 }
18 int start()
19 {
20 int cnt1=0,cnt2=0,st,i;
21 for(i=0;i<26;i++)
22 {
23 if(abs(degree_in[i]-degree_out[i])==2)
24 return -1;
25 else if(degree_in[i]-degree_out[i]==1)
26 cnt1++;
27 else if(degree_in[i]-degree_out[i]==-1)
28 {
29 cnt2++;
30 st=i;
31 }
32 }
33 if(cnt1>1||cnt2>1)
34 return -1;
35 else if(cnt1==0)//可形成环,因此找到从前往后最大的节点即可
36 {
37 for(i=0;i<26;i++)
38 if(degree_out[i])
39 return i;
40 }
41 else
42 return st;
43 }
44 bool dfs(int st,int cnt)
45 {
46 int i;
47 if(cnt==n)
48 return 1;
49 for(i=0;i<n;i++)
50 {
51 if(edge[i].st<st||used[i])
52 continue;
53 else if(edge[i].st>st)
54 return false;
55 used[i]=true;
56 edge_order[cnt]=i;
57 if(dfs(edge[i].en,cnt+1))
58 return 1;
59 used[i]=false;//回溯判断是否形成欧拉路径
60 }
61 return false;
62 }
63 int main()
64 {
65 int t,i;
66 cin>>t;
67 while(t--)
68 {
69 cin>>n;
70 memset(used,false,sizeof(used));
71 memset(degree_out,0,sizeof(degree_out));
72 memset(degree_in,0,sizeof(degree_in));
73 for(i=0;i<n;i++)
74 {
75 char s[30];
76 scanf("%s",s);
77 strcpy(edge[i].str,s);
78
79 int a,b;
80 a=s[0]-'a';
81 int len=strlen(s);
82 b=s[len-1]-'a';
83
84 degree_out[a]++;
85 degree_in[b]++;
86 edge[i].st=a; //把一个单词作为一条边,单词的首字母作为一个顶点与单词的尾字母连一条边
87 edge[i].en=b;
88 }
89 int st=start(); //寻找起点,先判断是否能形成欧拉路径,条件为所有点入度==出度或者是有一个点的入度比出度大一且还有个点的入度比出度小一
90 if(st==-1)
91 {
92 cout<<"***"<<endl;
93 continue;
94 }
95 sort(edge,edge+n,cmp);//所有的边按字典序排序
96 if(!dfs(st,0))
97 {
98 cout<<"***"<<endl;
99 continue;
100 }
101 printf("%s",edge[edge_order[0]].str);
102 for(i=1;i<n;i++)
103 printf(".%s",edge[edge_order[i]].str);
104 cout<<endl;
105 }
106 return 0;
107 }