Tip: 这道大家可能会对字典序产生害怕???
题意:问所有的单词是否能完成单词接龙,每个单词只能使用一次;
典型的...(有向欧拉图+有向半欧拉图)判断,并输出欧拉路径
题解:输出完对字符串进行排序(按字典序从大到小排序),利用链式前向星把图表示出来..(此时图是按字典序从小到大排序)
判断是不是欧拉图,是不是半欧拉图..然后输出欧拉路径...(此时欧拉路径的第一条边是字典序最大的....所以要从第n条边往前输出)
#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define CLR(x,y) memset(x,y,sizeof(x))
using namespace std;
const int mmax = 26;
/*
得知道有多少个点 ,pn记录点个数
pv记录点是否被访问
*/
struct Edge{
string str;
int to,next;
}e[mmax*100];
bool cmp(const Edge & a, const Edge &b){
return a.str > b.str;
}
int rela[mmax], head[mmax],in[mmax],out[mmax],cnt,pn,vis[mmax*100],pv[mmax],path[mmax*100],id;
int ff(int x){
if(rela[x] == -1 ) return x ;
return rela[x] = ff(rela[x]);
}
void init(){
CLR(head,-1);
CLR(rela,-1);
CLR(vis,0);
CLR(pv,0);
CLR(in,0);
CLR(out,0);
cnt = 1;
id = 0;
pn = 0;
}
void unit(const string & str,const int & i){
int fir = str[0]-'a';
int sec = str[str.length()-1] - 'a';
if(pv[fir] == 0) { pn++ ; pv[fir] = 1;}
if(pv[sec] == 0) { pn++ ; pv[sec] = 1;}
e[i].to = sec;
e[i].next = head[fir];
head[fir] = i;
out[fir]++;
in[sec]++;
int x = ff(fir);
int y = ff(sec);
if(x == y) return ;
rela[x] = y;
cnt++;
}
bool judge(int &s){
if(cnt != pn) return false;//pn代表有多少个结点,cnt是连接了多少块结点,判连通
int num = 0,s1 = -1,s2 = -1; //num记录度数不一样,ok
for(int i = 0 ; i < 26 ; i++){
if(out[i] - in[i] == 1) { s1 = i ; }
if(in[i] - out[i] == 1) {s2 = i;}
if(in[i] != out[i]) num++;
}
if(s1 != s2 && s2 != -1 && s1 != -1 && num == 2 ) { s = s1 ; return true; }
if(num == 0) {
for(int i = 0 ; i < 26 ; i++){
if(in[i] != 0){ s = i ;break;}
}
return true;
}
return false;
}
void dfs(int u){
for(int k = head[u] ; k != -1 ;k = e[k].next){
if(!vis[k]){
vis[k] = 1;
dfs(e[k].to);
path[id++] = k;
}
}
}
void show (int s){
dfs(s);
for(int i = id-1 ; i >= 0 ;i--){
if(i != 0) cout << e[ path[i] ].str <<".";
else cout << e[ path[i] ].str ;
}
cout << endl;
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int n,m ;
cin >> n ;
while(n--){
cin >> m;
init();
for(int i = 0 ; i < m ; i++){ cin >> e[i].str; }
sort(e,e+m,cmp);
for(int i = 0 ; i < m ;i++){
unit(e[i].str,i); //合并并做构图处理
}
int star = 0;
if(!judge(star)) cout << "***" << endl;
else show(star);
}
}