POJ 2337 Catenyms 欧拉回路

来源:互联网 发布:高通unity3d 编辑:程序博客网 时间:2024/05/20 14:27
CatenymsTime Limit: 1000MS      Memory Limit: 65536KTotal Submissions: 11660        Accepted: 3037DescriptionA 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.gophergopher.ratrat.tigeraloha.alohaarachnid.dogA 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.tigerGiven a dictionary of lower case words, you are to find a compound catenym that contains each of the words exactly once.InputThe 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.OutputFor 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 Input26alohaarachniddoggopherrattiger3oakmapleelmSample Outputaloha.arachnid.dog.gopher.rat.tiger***SourceWaterloo local 2003.01.25

http://blog.csdn.net/LuRiCheng/article/details/52415262的升级版
如果把字母当做点
把单词当做边 例如:dog=>从d到g的有向边
建图后 不难发现 这其实就是欧拉回路的变种 一笔画问题
至于输出回路 dfs即可
PS:POJ不支持string.back() 真蛋疼

#include<iostream>#include<stdlib.h>#include<stdio.h>#include<string>#include<vector>#include<deque>#include<queue>#include<algorithm>#include<set>#include<map>#include<stack>#include<time.h>#include<math.h>#include<list>#include<cstring>#include<fstream>//#include<memory.h>using namespace std;#define ll long long#define ull unsigned long long#define pii pair<int,int>#define INF 1000000007#define pll pair<ll,ll>#define pid pair<int,double>const int N=1000+5;//最大边数vector<string>vec;//边int inDegree[26];//入度int outDegree[26];//出度int par[26];//并查集vector<int>G[26];//邻接表 G[i]保存从i出发的边的下标 下标按边的字典序排序bool used[N];//dfs标记deque<string>ans;//答案inline int find(int i){    return par[i]=(par[i]==i?i:find(par[i]));}inline void unite(int i,int j){    par[find(i)]=find(j);}void builtG(){    for(int i=0;i<26;++i)        G[i].clear();    //对边进行排序 dfs时按顺序搜索 找到的第一个合法回路就是字典序最小的回路    sort(vec.begin(),vec.end());    for(int i=0;i<vec.size();++i){        int st=vec[i][0]-'a';        G[st].push_back(i);    }}void dfs(int in){    for(int i=0;i<G[in].size();++i){        int strIndex=G[in][i];        if(!used[strIndex]){            used[strIndex]=true;            int to=vec[strIndex][vec[strIndex].size()-1]-'a';            dfs(to);            ans.push_front(vec[strIndex]);        }    }}int main(){    //freopen("/home/lu/文档/r.txt","r",stdin);    //freopen("/home/lu/文档/w.txt","w",stdout);    int T;    scanf("%d",&T);    while(T--){        int n;        scanf("%d",&n);        vec.clear();        vec.resize(n);        //ini        fill(inDegree,inDegree+26,0);        fill(outDegree,outDegree+26,0);        for(int i=0;i<26;++i)            par[i]=i;        for(int i=0;i<n;++i){            cin>>vec[i];            int st=vec[i][0]-'a';            int end=vec[i][vec[i].size()-1]-'a';            ++outDegree[st];            ++inDegree[end];            unite(st,end);        }        //check is-unicom        int numOfSet=0;//检测所有边是否在一个联通集合中        for(int i=0;i<26;++i)            numOfSet+=(inDegree[i]+outDegree[i]>0&&par[i]==i);        if(numOfSet>1){            printf("***\n");            continue;        }        //check inDegree and outDegree        int in=-1,out=-1;//检测入度出度是否符合一笔画        bool noResult=false;        for(int i=0;i<26;++i){            int dt=inDegree[i]-outDegree[i];            if(dt==1){                if(out>=0){                    noResult=true;                    break;                }                out=i;            }            else                if(dt==-1){                    if(in>=0){                        noResult=true;                        break;                    }                    in=i;                }                else                    if(dt!=0){                        noResult=true;                        break;                    }        }        if(noResult){            printf("***\n");            continue;        }    //dfs找出回路        fill(used,used+n,false);        builtG();        ans.clear();        if(in>=0)            dfs(in);        else            for(int i=0;i<26;++i)                if(inDegree[i]>0){                    dfs(i);                    break;                }        cout<<ans.front();        for(int i=1;i<ans.size();++i)            cout<<"."<<ans[i];        cout<<endl;    }    return 0;}
0 0
原创粉丝点击