poj------Catenyms

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
***
题意:给你一些单词,能否将这些单词首尾连接起来,即前一个单词的最后一个字母和后一个单词的第一个字母相同,若能输出该序列,若有多种则按字典序输出该序列。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int n,vis[1005],len[1005],k,in[27],out[27];
int ans[1005],cnt;
string s[1005];
struct node
{
    int u,m;
};
vector<node> g[27];
void euler(int x)
{
    for(int i=0; i<g[x].size(); i++)
    {
        int v=g[x][i].u;
        if(!vis[g[x][i].m])
        {
            vis[g[x][i].m]=1;
            euler(v);
            cnt++;
            ans[cnt]=g[x][i].m;//,记录路径编号,从而保存路径
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int start=100;
        cin >> n;
        cnt=k=0;
        memset(vis,0,sizeof(vis));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        for(int i=1; i<=26; i++)
            g[i].clear();
        for(int i=1; i<=n; i++)
            cin >> s[i];
        sort(s+1,s+n+1);
        start=s[1][0]-'a'+1;
//        for(int i=1;i<=n;i++)
//        {
//            cout<<s[i]<<" ";
//        }
        for(int i=1; i<=n; i++)
            len[i]=s[i].size();
        for(int i=1; i<=n; i++)
        {
            node t;
            t.u=s[i][len[i]-1]-'a'+1;
            t.m=i;
            g[ s[i][0]-'a'+1 ].push_back( t );
            out[ s[i][0]-'a'+1 ]++;
            in[s[i][len[i]-1]-'a'+1]++;
//            start=min(start,s[i][0]-'a'+1);
//            start=min(start,s[i][len[i]-1]-'a'+1);
        }
        //printf("%d\n",start);
        int fin=0,fout=0,flag=0;
        for(int i=1; i<=26; i++)//判断能不能构成欧拉回路
        {
            if(in[i]+1==out[i])
            {
                start=i;//一定要更新,因为虽然排序了,但是排序后的字符串有可能不能构成欧拉回路,比如:
                //bdsfda  asdjfdsuc csdfgfd dfdfewre efef,它排序之后为asdjfdsuc  bdsfda csdfgfd dfdfewre efef
                //显然按这个顺序是不能构成回路的,所以要重新更新start
                fin++;//等于1 的话就说明单词的首尾字母是相同的,等于0就说明不相同,
            //等于其它就说明首尾已经不能相连了,也就不能构成欧拉回路了
            }//先把单词按字典序排序,然后判断是欧拉回路还是只是欧拉通路,如果是欧拉回路,直接从第0号单词开始搜,
            //否则,找到出度比入度大1的那个单词开始搜。
            else if(in[i]==out[i]+1)
            {
                fout++;//同上
            }
            else if(in[i]!=out[i]) flag=1;
        }
        //cout<<fin<<" "<<fout<<endl;
        if(flag==1)
        {
            printf("***\n");
            continue;
        }
        else if( (fin==1&&fout==1) || (fin==0&&fout==0) )
        {
            cnt=0;
            euler(start);
            if(cnt==n)
            {
                for(int i=cnt; i>=1; i--)
                {
                    if(i==cnt)
                        cout << s[ ans[i] ];
                    else
                        cout << "." << s[ ans[i] ];
                }
//                for(int i=1;i<=n;i++)
//                {
//                    if(i==1)
//                        cout<<s[i];
//                    else
//                        cout<<"."<<s[i];
//                }
/*
5 ab ba ab ba ab,这样的样列就不能过,所以这样输出是错的
*/
                printf("\n");
            }
            else
            {
                printf("***\n");
                continue;
            }
        }
        else
        {
            printf("***\n");
            continue;
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值