-和尚-

导航

Catenyms

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 first letter of the second. For example, the following are catenyms: 

dog.gophergopher.ratrat.tigeraloha.alohaarachnid.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
***

这道题就是求给出的单词是否能首尾相连。能就输出他的首尾相连的序列,有多个就按字典序列输出!

这道题一开始我用暴力搜,结果超时了!人家说可以,我个人觉得不行,可能我自己的代码太烂吧!最后没办法百度,原来就是用欧拉回路!顺便说一次下欧拉回路吧!

对无向图:  

定义:给定无孤立结点图G,若存在一条路,经过图中每条边一次且仅仅一次,该条路称欧拉路,若存在一条回路,经过图中每边一次且仅仅一次,该回路称为欧拉回路。具有欧拉回路的图称为欧拉图。

定理:无向图G具有一条欧拉路,当且仅当G是连通的,且有0个或者是两个奇数度得结点。

推论:无向图G具有一条欧拉回路,当且仅当G是连通的,并且所有结点的度数均为偶数。

一笔画问题就是典型的这类问题:要判定一个图G是否可一笔画出,有两种情况, 从图中某一个结点出发,经过图G中每个边一次再回到该结点,或者是从G中某一个结点出发,经过G中每边一次且仅一次到达另一个结点,分别对应着欧拉回路和欧拉路的问题

 对有向图:

定义:给定有向图G,通过图中每边一次且仅一次的一条单向路(回路),称作单向欧拉路(回路)。

定理:有向图G具有单向欧拉路,当且仅当它是连通的,而且除两个结点外,每个结点的入度等于出度,但这两个结点中,一个结点的入度比出度大1,另一个结点的入度比出度小1。 

定理:有向图G具有一条单向欧拉回路,当且仅当是连通的,且每个结点入度等于出度。

代码:(TLE)

#include<algorithm>

#include<string>

 

using namespace std;

 

struct edge

 

{

 

    int y,end;

 

    char str[100];

 

}ss[10005];

 

bool cmp(edge a,edge b) 

 

 

    return strcmp(a.str,b.str)<0; 

 

}

 

int da[100000],n,vist[1000000],g;

 

void dfs(int k)

 

{

 

    int j,i;

 

    if(g==n)

 

        return;

 

    for(i=0;i<n;i++)

 

    {

 

        if(vist[i]==0&&ss[k].str[ss[k].end]==ss[i].str[0])

 

        {

 

            vist[i]=1;

 

            da[g++]=i;

 

            dfs(i);

 

        }

 

    }

 

}

 

int main()

 

{

 

    int i,j,fx,fy,T,s,k;

 

    scanf("%d",&T);

 

    while(T--)

 

    {

 

        scanf("%d",&n);

 

        for(i=0;i<n;i++)

 

        {

 

            scanf("%s",ss[i].str);

 

            ss[i].y=0;ss[i].end=strlen(ss[i].str)-1;

 

        }

 

        sort(ss,ss+n,cmp);

 

        da[0]=0;g=0;

 

        for(i=0;i<n;i++)

 

        {

 

            memset(vist,0,sizeof(vist));

 

            vist[i]=1;

 

            dfs(i);

 

        }

 

        if(g==n)

 

        {

 

            printf("%s.",ss[0].str);

 

            for(i=0;i<n-1;i++)

 

                printf("%s.",ss[da[i]].str);

 

            printf("%s",ss[da[i]].str);

 

        }

 

        else

 

            printf("***");

 

        printf("\n");

 

    }

 

    return 0;

 

}
代码:AC
#include<algorithm>
#include<iostream>
using namespace std;
int in[30],out[30],order[1000],n;bool used[1000];
struct Edge
{
    int st,en;
    char str[30];
}edge[1000];
bool cmp(Edge a,Edge b)
{
    return strcmp(a.str,b.str)<0;
}
int start()
{
    int cnt1=0,cnt2=0,st,i;
    for(i=0;i<26;i++)
    {
        if(abs(in[i]-out[i])==2)
            return -1;
        else if(in[i]-out[i]==1)
            cnt1++;
        else if(in[i]-out[i]==-1)
        {
            cnt2++;
            st=i;
        }
    }
    if(cnt1>1||cnt2>1)
        return -1;
    else if(cnt1==0)
    {
        for(i=0;i<26;i++)
            if(out[i])
                return i;
    }
    return st;
}
bool dfs(int st,int cnt)
{
    int i;
    if(cnt==n)
        return 1;
    for(i=0;i<n;i++)
    {
        if(edge[i].st<st||used[i])
            continue;
        else if(edge[i].st>st)
            return false;
        used[i]=true;
        order[cnt]=i;
        if(dfs(edge[i].en,cnt+1))
            return 1;
        used[i]=false;//回溯判断是否形成欧拉路径
    }
    return false;
}
int main()
{
    int t,i,a,b,len;
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(used,false,sizeof(used));memset(out,0,sizeof(out));memset(in,0,sizeof(in));
        for(i=0;i<n;i++)
        {
            scanf("%s",edge[i].str);
            a=edge[i].str[0]-'a';
            len=strlen(edge[i].str);
            b=edge[i].str[len-1]-'a';
            out[a]++;
            in[b]++;
            edge[i].st=a;
            edge[i].en=b;
        }
        int st=start();//寻找起点,先判断是否能形成欧拉路径,条件为所有点入度==出度或者是有一个点的入度比出度大一且还有个点的入度比出度小一
        if(st==-1)
        {
            cout<<"***"<<endl;
            continue;
        }
        sort(edge,edge+n,cmp);
        if(!dfs(st,0))
        {
            cout<<"***"<<endl;
            continue;
        }
        printf("%s",edge[order[0]].str);
        for(i=1;i<n;i++)
            printf(".%s",edge[order[i]].str);
        cout<<endl;
    }
    return 0;
}

 

posted on 2012-08-04 18:46  -和尚-  阅读(127)  评论(0编辑  收藏  举报