POJ 2337 Catenyms (欧拉回路)

Catenyms
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 8173   Accepted: 2149

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

 

题目大意:输入n个单词,每个单词都形成一条从该单词首字母到尾字母的边,单词尾字母要与下一个单词首字母相同,若可以组成这样的路,即可以组成这样一条连着的单词串,输出路径(单词串),若有多条,则要按字典顺序输出,找不到路则输出***。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

int n,cnt,head[30];
int tot,odd,src,des,mark[30],indeg[30],outdeg[30],deg[30],father[30];
char res[1010][30];

struct Edge{
    bool vis;
    char wrd[30];
    int to,nxt;
}edge[1010];

int cmp(Edge a,Edge b){
    return strcmp(a.wrd,b.wrd)>0;
}

void init(){
    tot=odd=0;
    memset(mark,0,sizeof(mark));
    memset(indeg,0,sizeof(indeg));
    memset(outdeg,0,sizeof(outdeg));
    memset(head,-1,sizeof(head));
    for(int i=0;i<1010;i++)
        edge[i].vis=0;
    for(int i=0;i<26;i++)
        father[i]=i;
}

int findSet(int x){
    if(x!=father[x]){
        father[x]=findSet(father[x]);
    }
    return father[x];
}

int judge(){    //判断是否满足欧拉。0不满足,1欧拉回路,2欧拉路 
    int i,k;
    for(i=0;i<26;i++){  //判断有向图欧拉 
        if(!mark[i])
            continue;
        deg[i]=indeg[i]-outdeg[i];
        if(abs(deg[i])>1)
            return 0;
        if(deg[i]>0)    src=i;    //起点
        if(deg[i]<0)    des=i;    //终点 
        if(deg[i]%2)    odd++;
        if(odd>2)   return 0;
    }
    for(i=0;i<26;i++)
        if(mark[i])
            break;
    k=findSet(i);
    for(i=k+1;i<26;i++){    //判断连通性 
        if(!mark[i])
            continue;
        if(k!=findSet(i))
            return 0;
    }
    if(odd==0){     //有欧拉回路  
        for(i=0;i<26;i++)
            if(mark[i])
                break;
        src=i;
        return 1;
    }
    return 2;
}

void DFS(int u,int id){     //深搜寻找欧拉路径,
    for(int i=head[u];i!=-1;i=edge[i].nxt)
        if(!edge[i].vis){
            edge[i].vis=1;
            DFS(edge[i].to,i);
        }
    if(id!=-1)
        strcpy(res[tot++],edge[id].wrd);    //最先进去的肯定是终点 
}

int main(){

    //freopen("input.txt","r",stdin);

    int t;
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%s",edge[i].wrd);
        sort(edge,edge+n,cmp);  //题目要求是字典顺序,但是我是用前插链表,这时的顺序恰好会相反 ,所以排序时从大到小,这样刚刚会是字典顺序
        for(int i=0;i<n;i++){
            int len=strlen(edge[i].wrd);
            int x=edge[i].wrd[0]-'a';
            int y=edge[i].wrd[len-1]-'a';
            indeg[x]++;     outdeg[y]++;
            mark[x]=true;   mark[y]=true;

            edge[i].to=y;   edge[i].nxt=head[x];    head[x]=i;  //建边

            int fx=findSet(x);
            int fy=findSet(y);
            if(fx!=fy)
                father[fx]=fy;
        }
        if(judge()==0){
            printf("***\n");
            continue;
        }
        DFS(src,-1);
        for(int i=tot-1;i>0;i--)
            printf("%s.",res[i]);
        printf("%s\n",res[0]);
    }
    return 0;
}

 

posted @ 2013-07-04 09:19  Jack Ge  阅读(288)  评论(0编辑  收藏  举报