您的位置:首页 > 其它

poj2337Catenyms(有向欧拉图:输出欧拉路径)

2016-02-02 11:40 344 查看
题意:给你一组N个单词,现在要你输出这样一组单词序列。该序列包含了所有N个单词,且该序列中的前一个单词的最后一个字母与后一个单词的第一个字母相同。如果存在多个这种首尾相连的序列,就输出字典序最小的那个即可。

思路:首先我们把每个单词看成一条边,把每个单词的首尾两个小写字母看成节点(不一定存在所有26个节点),其实就是在找一条欧拉路径。麻烦的是这道题目并没有告诉一定存在欧拉路,所以还需要判断是否存在

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 1000+10
#define LL long long
int cas=1,T;
struct word
{
int len;
char s[50];
bool operator < (const word &rhs)const
{
return strcmp(s,rhs.s)<0;
}
}words[maxn];
struct Edge
{
int u,v;
bool vis;
}edges[maxn];
int pre[maxn];
int in[maxn];
int out[maxn];
int mark[maxn];
int m;
int cnt,ans[maxn];
int Find(int x)
{
return pre[x]==-1?x:pre[x]=Find(pre[x]);
}
bool check()
{
int k = 0;
for (int i = 0;i<26;i++)
if (mark[i])
if (Find(i)==i)
k++;
return k==1;
/**if (k==1)
return true;
else
return false;*/
}
void euler(int u)
{
for (int i = 0;i<m;i++)
if (!edges[i].vis && edges[i].u==u)
{
edges[i].vis=1;
euler(edges[i].v);
ans[cnt++]=i;
}
}
int main()
{
//freopen("in","r",stdin);
scanf("%d",&T);
while (T--)
{
scanf("%d",&m);
for (int i = 0;i<m;i++)
{
scanf("%s",words[i].s);
words[i].len = strlen(words[i].s);
}
sort(words,words+m);
memset(pre,-1,sizeof(pre));
memset(mark,0,sizeof(mark));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for (int i = 0;i<m;i++)
{
int u,v;
u=words[i].s[0]-'a';
v=words[i].s[words[i].len-1]-'a';
edges[i].u=u;
edges[i].v=v;
edges[i].vis=0;
in[v]++;
out[u]++;
mark[u]=mark[v]=1;
u=Find(u);
v=Find(v);
if (u!=v)
pre[u]=v;
}
int start=edges[0].u;
int i,c1=0,c2=0;
for (i = 0;i<26;i++)
{
if (mark[i])
{
if (in[i]==out[i])continue;
else if (in[i]-out[i]==1) c1++;
else if (out[i]-in[i]==1) c2++,start=i;
else break;
}
}
if (i==26 && ((c1==c2&&c1==0) || (c1==c2&&c1==1)) && check())
{
cnt=0;
euler(start);
printf("%s",words[ans[cnt-1]].s);
for (int i = cnt-2;i>=0;i--)
{
printf(".%s",words[ans[i]].s);
}
printf("\n");
}
else
printf("***\n");
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return 0;
}


题目

Description

A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For example, the following are catenyms:

dog.gopher
gopher.rat
rat.tiger
aloha.aloha
arachnid.dog


A compound catenym is a sequence of three or more words separated by periods such that each adjacent pair of words forms a catenym. For example,

aloha.aloha.arachnid.dog.gopher.rat.tiger

Given a dictionary of lower case words, you are to find a compound catenym that contains each of the words exactly once.

Input

The first line of standard input contains t, the number of test cases. Each test case begins with 3 <= n <= 1000 - the number of words in the dictionary. n distinct dictionary words follow; each word is a string of between 1 and 20 lowercase letters on a line
by itself.

Output

For each test case, output a line giving the lexicographically least compound catenym that contains each dictionary word exactly once. Output "***" if there is no solution.

Sample Input

2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm


Sample Output

aloha.arachnid.dog.gopher.rat.tiger
***
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: