POJ 2337 Catenyms (欧拉回路)

52 篇文章 0 订阅
Catenyms
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 7828 Accepted: 2057

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
***

Source

思路:明显得告诉你了每个单词用一次,也就是经过一次。对于每个单词,从首字母到尾字母连接一条有向边,求出欧拉回路即可;这里要求要用最小字典序来写,那么需要对原字符串排序,怎么排序看你如何建边了,我是邻接表带头指针逆向建边的,所以按从大到小排序;至于有向图的欧拉判定可以百度学习下,对于这题,我没有判断他的连通性。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=30;
const int maxm=1005;
struct node
{
    char ch[25];
    int l;
} data[maxm];
char output[maxm][25];
int to[maxm],next[maxm],ans[maxm];
int head[maxn],edge,ansi,degree[maxn];
bool vis[maxm],used[maxn];
bool cmp(node a,node b)
{
    return strcmp(a.ch,b.ch)>0;
}
inline void add(int u,int v,char a[])
{
    strcpy(output[edge],a);
    to[edge]=v,next[edge]=head[u],head[u]=edge++;
}
void init()
{
    edge=ansi=0;
    memset(degree,0,sizeof(degree));
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(used,0,sizeof(used));
}
void dfs(int now)
{
    for(int i=head[now]; ~i; i=next[i])
        if(!vis[i])
        {
            vis[i]=1;
            dfs(to[i]);
            ans[ansi++]=i;
        }
}
bool ok(int &u,int &v)
{
    u=0,v=0;
    bool f=0;
    for(int i=1; i<=26; i++)
        if(used[i])
        {
            if(!degree[i]) continue;
            f=1;
            if(degree[i]==-1)
            {
                if(u)
                {
                    u=0;
                    break;
                }
                u=i;
            }
            else if(degree[i]==1)
            {
                if(v)
                {
                    v=0;
                    break;
                }
                v=i;
            }
            else
            {
                u=0;
                break;
            }
        }
    if(!f)
    {
        for(int i=1; i<=26; i++)
            if(used[v=i]) return true;
    }
    if(u&&v) return true;
    else return false;
}
int main()
{
    int ca,n,u,v;
    scanf("%d",&ca);
    while(ca--)
    {
        scanf("%d",&n);
        init();
        for(int i=0; i<n; i++)
        {
            scanf("%s",data[i].ch);
            data[i].l=strlen(data[i].ch);
        }
        sort(data,data+n,cmp);
        for(int i=0; i<n; i++)
        {
            u=data[i].ch[0]-'a'+1;
            v=data[i].ch[data[i].l-1]-'a'+1;
            degree[u]++,degree[v]--;
            add(u,v,data[i].ch);
            used[u]=used[v]=1;
        }
        if(ok(u,v))
        {
            dfs(v);
            if(ansi<n)
            {
                puts("***");
                continue;
            }
            for(int i=ansi-1; i>=0; i--)
            {
                if(i==ansi-1) printf("%s",output[ans[i]]);
                else printf(".%s",output[ans[i]]);
            }
            printf("\n");
        }
        else puts("***");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值