题目链接:http://poj.org/problem?id=2337
题意:问你所有的字符串能否首尾相连在一起,如果能,输出字典序最小的那一串东西,否则输出*
解析:对于输入所有字符串先排个序,然后逆序建图,这样就搜的时候就是优先选择字典序小的字符串,然后就是判是否符合题意,搜的时候记录一下结果
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int maxn = 5005;
struct node
{
int flag;
int next;
int to;
int id;
}edge[maxn];
int head[maxn],cnt,cur;
int vis[maxn],out[maxn],in[maxn];
int ans[maxn];
string a[maxn];
void init()
{
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
memset(out,0,sizeof(out));
memset(in,0,sizeof(in));
cnt = cur = 0;
}
void addEdge(int from,int to,int index)
{
edge[cnt].id = index;
edge[cnt].to = to;
edge[cnt].next = head[from];
edge[cnt].flag = 0;
head[from] = cnt++;
}
void dfs(int i)
{
for(int j=head[i];j!=-1;j = edge[j].next)
{
if(!edge[j].flag)
{
edge[j].flag = 1;
dfs(edge[j].to);
ans[cur++] = edge[j].id;
}
}
}
int main(void)
{
int t,n;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
int start = maxn;
for(int i=n-1;i>=0;i--)
{
int len = a[i].length();
int s = a[i][0]-'a';
int t = a[i][len-1]-'a';
addEdge(s,t,i);
vis[s] = vis[t] = 1;
out[s]++,in[t]++;
if(s<start) start = s;
if(t<start) start = t;
}
int flag = 1,scnt = 0,ecnt = 0;
for(int i=0;i<100;i++)
{
if(out[i]!=in[i])
{
if(out[i]-in[i]==1)
start = i,scnt++;
else if(out[i]-in[i]==-1)
ecnt++;
else
flag = 0;
}
}
if(flag&&((scnt==0 && ecnt==0)||(scnt==1 && ecnt==1)))
{
dfs(start);
if(cur!=n)
puts("***");
else
{
for(int i=cur-1;i>=0;i--)
{
if(i!=cur-1)printf(".");
cout<<a[ans[i]];
}
puts("");
}
}
else
puts("***");
}
return 0;
}