有向图欧拉通路

2337

Catenyms
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 9454 Accepted: 2486

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
***
分析:

题目的意思是给出来n个单词,看看是否能连成一条单词串,要把每个单词都搜索一遍很容易想到是欧拉通路,以每个单词的首字母和末字母为定点建边,权值状态为该单词,编号a,b,c……为1,2,3,……

首先用并查集判断改图是否是连通图不是的话输出***

然后判断该图是欧拉通路还是欧拉回路,若是欧拉回路的话从最小的点开始深搜,若是欧拉通路的话从出度比入度大一的点开始深搜,否则输出***

此题还让输出结果保证字典序最小,让单词按照逆序快排即可

定义:

1.无向图存在欧拉回路的充要条件:

   连通且没有奇度顶点。

2.无向图存在欧拉路径的充要条件:

   连通且奇度顶点个数为2

3.有向图存在欧拉路径的充要条件:

   基图连通且存在某顶点入度比出度大1,另一顶点出度比入度大1,其余顶点入度等于出

4.有向图存在欧拉回路的充要条件:

   基图连通且所有顶点入度等于出度。

程序:

#include"stdio.h"
#include"string.h"
#include"queue"
#include"stack"
#include"iostream"
#include"string"
#include"map"
#include"stdlib.h"
#define inf 99999999
#define M 10009
using namespace std;
struct st
{
    int u,v,w,next,vis;
}edge[M];
int head[M],use[M],s[M],out[M],in[M];
int t,num;
int f[M];
int finde(int x)
{
    if(x!=f[x])
        f[x]=finde(f[x]);
    return f[x];
}
void make(int a,int b)
{
    f[finde(a)]=finde(b);
}
int cmp(const void *a,const void *b)
{
    return strcmp((char *)b,(char *)a);
}
void init()
{
    t=0;
    memset(head,-1,sizeof(head));
    memset(out,0,sizeof(out));
    memset(in,0,sizeof(in));
    memset(use,0,sizeof(use));
    memset(edge,0,sizeof(edge));
    for(int i=0;i<=100;i++)
        f[i]=i;
}
void add(int u,int v,int w)
{
    edge[t].u=u;
    edge[t].v=v;
    edge[t].w=w;
    edge[t].next=head[u];
    head[u]=t++;
}
void DFS(int u)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!edge[i].vis)
        {
            edge[i].vis=1;
            DFS(v);
            s[num++]=edge[i].w;
        }
    }
}
char ch[M][111];
int main()
{
    int T,i,a,b,n,m;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
            scanf("%s",ch[i]);
        qsort(ch,n,sizeof(ch[0]),cmp);
        init();
        for(i=0;i<n;i++)
        {
            m=strlen(ch[i]);
            a=ch[i][0]-'a'+1;
            b=ch[i][m-1]-'a'+1;
            use[a]=1;
            use[b]=1;
            make(a,b);
            add(a,b,i);
            out[a]++;
            in[b]++;
        }
        int tmp=finde(a);
        int flag=0;
        for(i=1;i<=26;i++)
        {
            if(use[i]&&finde(i)!=tmp)
                flag++;
        }
        if(flag)
        {
            printf("***\n");continue;
        }
        int f1=0,f2=0,ff=0;
        for(i=1;i<=26;i++)
        {
            if(!use[i])
                continue;
            if(out[i]-in[i]>1||in[i]-out[i]>1)
                ff++;
            if(out[i]==in[i]+1)
                f1++;
            if(out[i]+1==in[i])
                f2++;
        }
        if(f1==0&&f2==0&&ff==0)
        {
            num=0;
            for(i=1;i<=26;i++)
            {
                if(use[i])
                {
                    DFS(i);
                    break;
                }
            }
            for(i=num-1;i>=0;i--)
            {
                if(i==num-1)
                    printf("%s",ch[s[i]]);
                else
                    printf(".%s",ch[s[i]]);
            }
            printf("\n");
        }
        else if(f1==1&&f2==1&&ff==0)
        {
            num=0;
            for(i=1;i<=26;i++)
            {
                if(use[i]&&in[i]+1==out[i])
                {
                    DFS(i);
                    break;
                }
            }
            for(i=num-1;i>=0;i--)
            {
                if(i==num-1)
                    printf("%s",ch[s[i]]);
                else
                    printf(".%s",ch[s[i]]);
            }
            printf("\n");
        }
        else
            printf("***\n");
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值