zoukankan      html  css  js  c++  java
  • 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("***
    ");
                continue;
            }
            DFS(src,-1);
            for(int i=tot-1;i>0;i--)
                printf("%s.",res[i]);
            printf("%s
    ",res[0]);
        }
        return 0;
    }
  • 相关阅读:
    ecshop ajax请求验证captcha(验证码)
    ecshop ajax内置函数Ajax.call
    Execl中函数使用总结
    php应用篇 PHPMailer使用
    Jquery中的选择器
    你的水桶有多满
    在纸上写todo list还是用APP?
    absolute居中
    搬家租房总结
    编译器的作用:将汇编语言翻译成机器语言
  • 原文地址:https://www.cnblogs.com/jackge/p/3170895.html
Copyright © 2011-2022 走看看