题目链接:http://poj.org/problem?id=2337
题目大意:给出n个单词,找出他们之间一条字典序最小的连接路径。两个单词能连接当且仅当前一个单词的尾字母等于后一个单词的首字母。
分析:单词接龙,POJ1386的升级,需要输出路径。我们可以先把这些单词排序,然后在进行建图,这样我们在dfs的时候就等于直接按字典序来搜索了。
实现代码如下:
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
struct EDGE
{
int to,nex;
int id;
bool flag;
}edge[2020];
int head[30],cnt;
void add(int u,int v,int id)
{
edge[cnt].to=v;
edge[cnt].nex=head[u];
edge[cnt].id=id;
edge[cnt].flag=false;
head[u]=cnt++;
}
string str[1010];
int ind[30];
int ans[1010],ansi;
void dfs(int x)
{
for(int i=head[x];i!=-1;i=edge[i].nex)
if(!edge[i].flag)
{
edge[i].flag=true;
dfs(edge[i].to);
ans[ansi++]=edge[i].id;
}
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
//scanf("%s",str[i]);
cin>>str[i];
sort(str,str+n);
cnt=0;
memset(head,-1,sizeof(head));
memset(ind,0,sizeof(ind));
int start=100;
for(int i=n-1;i>=0;i--)
{
int u=str[i][0]-'a';
int v=str[i][ str[i].length()-1 ]-'a';
add(u,v,i);
ind[u]--;
ind[v]++;
if(u<start) start=u;
if(v<start) start=v;
}
int ling=0,zheng=0,fu=0;
for(int i=0;i<26;i++)
{
if(ind[i]==0) ling++;
else if(ind[i]==1) zheng++;
else if(ind[i]==-1)
{
fu++;
start=i;
}
}
if(!(ling==26||(ling==24&&zheng==1&&fu==1)))
{
puts("***");
continue;
}
ansi=0;
dfs(start);
if(ansi<n)
{
puts("***");
continue;
}
for(int i=ansi-1;i>=0;i--)
{
//printf("%s",str[ ans[i] ]);
cout<<str[ ans[i] ];
if(i>0) printf(".");
else printf("\n");
}
}
return 0;
}
/*
测试数据(输出应和第一组样例一样)
2
6
arachnid
aloha
dog
gopher
rat
tiger
6
arachnid
tiger
gopher
aloha
rat
dog
*/