POJ - 2337 Catenyms(单词拼接)欧拉通路

本文探讨了欧拉路径和欧拉回路的概念及其在解决特定字符串序列问题中的应用。通过对输入字典中单词的分析,寻找符合特定条件的复合串,并利用图论中的欧拉路径理论来确定解决方案的存在性和最优性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

欧拉路径和欧拉回路
欧拉路径:从某结点出发一笔画成所经过的路线叫做欧拉路径。
欧拉回路:在欧拉路径的基础上又回到起点。
a、凡是由偶点组成的连通图,一定可以一笔画成。画时可以把任一偶点为起点,最后一定能以这个点为
终点画完此图。   
b、凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。画时必须把一个奇点为起点,另
一个奇点终点。  
c、其他情况的图都不能一笔画出。(有偶数个奇点除以2便可算出此图需几笔画成。)


欧拉回路和欧拉路径的判断
欧拉回路:
无向图:每个顶点的度数都是偶数,则存在欧拉回路。
有向图:每个顶点的入度都等于出度,则存在欧拉回路。
欧拉路径:
无向图:当且仅当该图所有顶点的度数为偶数 或者 除了两个度数为奇数外其余的全是偶数。
有向图:当且仅当该图所有顶点 出度=入度 或者 一个顶点 出度=入度+1,另一个顶点 入度=出度+1,其他顶点 出度=入度。

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct node
{
    char s[30];
    int start,end;

} a[1001];
int f[1001];
int cmp(node p,node q)
{
    return strcmp(p.s,q.s)<0;
}
int in[1001],out[1001],order[1001],m;
int fun()
{
    int x1,x2,ans=0,i;
    x1=x2=0;
    for(i=0; i<26; i++)
    {
        if(abs(in[i]-out[i])>=2)
            return -1;
        else if((in[i]-out[i])==1)//统计入度大于出度的顶点个数
            x1++;
        else if(in[i]-out[i]==-1)//统计出度大于入度的顶点个数
        {
            x2++;
            ans=i;//环路的起点
        }
    }
    if(x1>1||x2>1)
        return -1;
    else if(x1==0)
    {
        for(i=0; i<26; i++)
            if(out[i])
                return i;
    }
    else
        return ans;
}
int dfs(int st,int cnt)//深搜判断是否连通
{
    int i;
    if(cnt==m)
        return 1;
    for(i=0; i<m; i++)
    {
        if(a[i].start<st||f[i])
            continue;
        else if(a[i].start>st)
            return 0;
        f[i]=1;
        order[cnt]=i;
        if(dfs(a[i].end,cnt+1))
            return 1;
        f[i]=0;
    }
    return 0;
}
int main()
{
    int n,slen,i,t;
    scanf("%d",&n);
    while(n--)
    {
        memset(f,0,sizeof(f));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        scanf("%d",&m);
        for(i=0; i<m; i++)
        {
            scanf("%s",a[i].s);
            slen=strlen(a[i].s);
            a[i].start=a[i].s[0]-'a';
            a[i].end=a[i].s[slen-1]-'a';
            in[a[i].end]++;//尾字符作为入度
            out[a[i].start]++;//首字母作为出度
        }
        t=fun();//判断是否能形成欧拉路径
        sort(a,a+m,cmp);
        if(t==-1||!dfs(t,0))
        {
            printf("***\n");
            continue;
        }
        printf("%s",a[order[0]].s);
        for(i=1; i<m; i++)
            printf(".%s",a[order[i]].s);
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值