题意是求一个欧拉路,并以字典序输出
要欧拉路以字典序输出,则一开始将边进行排序,然后构图,选择字典序最小的可用点作为开始点查找欧拉路,然后倒序输出,即可。(不知道证明。。。。。)
// File Name: 2337.cpp // Author: zlbing // Created Time: 2013/3/10 15:36:00 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,n) for(int i=0;i<n;i++) #define REP1(i,n) for(int i=1;i<n+1;i++) #define MAXN 1000+50 struct Str{ char str[30]; }S[MAXN]; bool cmp(const Str& a,const Str& b){ int t=strcmp(a.str,b.str); if(t<=0)return true; else return false; } struct Edge{ int from,to; }; vector<Edge> edges; vector<int>G[MAXN]; int vis[MAXN]; vector<int>ans; void dfs(int u){ for(int i=0;i<G[u].size();i++){ int m=G[u][i]; if(vis[m])continue; vis[m]=1; dfs(edges[m].to); ans.push_back(m); } } int main(){ int cas; scanf("%d",&cas); while(cas--){ int n; scanf("%d",&n); REP(i,n){ scanf("%s",S[i].str); } sort(S,S+n,cmp); edges.clear(); REP(i,30)G[i].clear(); REP(i,n){ int len=strlen(S[i].str); edges.push_back((Edge){(int)(S[i].str[0]-'a'),(int)(S[i].str[len-1]-'a')}); int m=edges.size(); G[S[i].str[0]-'a'].push_back(m-1); } int degr[30],degc[30]; CL(degr,0); CL(degc,0); REP(i,26){ REP(j,G[i].size()){ degc[i]++; degr[edges[G[i][j]].to]++; } } int st=-1,et=-1; bool flag=false; int cnt=0; REP(i,26){ if(degc[i]!=degr[i]){ if(abs(degr[i]-degc[i])>1)flag=true; if(degr[i]-degc[i]!=0){ cnt++; if(degr[i]-degc[i]==1&&et==-1) et=i; else if(degc[i]-degr[i]==1&&st==-1) st=i; else flag=true; } } } if(flag||(cnt!=2&&cnt!=0)){ puts("***"); continue; } if(st==-1){ REP(i,26){ if(G[i].size()!=0){ st=i;break; } } } CL(vis,0); ans.clear(); dfs(st); if(ans.size()!=n){ puts("***"); continue; } printf("%s",S[ans[n-1]].str); for(int i=n-2;i>=0;i--)printf(".%s",S[ans[i]].str); printf("\n"); } return 0; }