poj 2337 欧拉回路输出最小字典序路径 ***
把26个小写字母当成点,每个单词就是一条边。
然后就是求欧拉路径。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> using namespace std; #define MOD 1000000007 const int INF=0x3f3f3f3f; const double eps=1e-5; typedef long long ll; #define cl(a) memset(a,0,sizeof(a)) #define ts printf("*****\n"); const int MAXN=2010; int n,m,tt; string s[MAXN]; int ans[MAXN],in[30],out[30]; struct Edge { int to,next; int id; bool vis; }edge[MAXN]; int head[30],tot; void init() { tot = 0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int id) { edge[tot].to=v; edge[tot].next=head[u]; edge[tot].id=id; edge[tot].vis=0; head[u]=tot++; } int cnt; bool dfs(int u) { for(int i=head[u];i!=-1;i=edge[i].next) { if(!edge[i].vis) { edge[i].vis=1; dfs(edge[i].to); ans[cnt++]=edge[i].id; } } } int main() { int i,j,k; #ifndef ONLINE_JUDGE freopen("1.in","r",stdin); #endif scanf("%d",&tt); while(tt--) { cnt=0; init(); scanf("%d",&n); for(i=0;i<n;i++) cin>>s[i]; sort(s,s+n); cl(in),cl(out); int u,v,st=100; for(i=n-1;i>=0;i--) //注意前向星是后加入的边先遍历 { u=s[i][0]-'a'; v=s[i][s[i].length()-1]-'a'; addedge(u,v,i); out[u]++; in[v]++; if(st>u) st=u; if(st>v) st=v; } int sc1=0,sc2=0; for(i=0;i<26;i++) { if(out[i]-in[i]==1) //只能从这出发 { sc1++; st=i; } else if(out[i]-in[i]==-1) //只能从这出发 { sc2++; } else if(out[i]-in[i]!=0) sc1=3; //不是欧拉回路 } if(!((sc1==1&&sc2==1)||(sc1==0&&sc2==0))) { printf("***\n"); continue; } dfs(st); if(cnt!=n)//判断是否连通 { printf("***\n"); continue; } for(int i=cnt-1;i>=0;i--) { cout<<s[ans[i]]; if(i>0)printf("."); else printf("\n"); } } }