POJ 2337 Catenyms

                       Catenyms
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 12658   Accepted: 3274

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

题意:给你一些单词,请你判断能否把他们首尾串起来串成一串,
前一个单词的结尾字母应该与下一个单词的首字母相同。
并且输出所有方案中字典序最小的方案。
吐槽:一直CE的我不想调他了,如果有大佬路过,可以帮忙看一下嘛?(*^__^*) 嘻嘻……
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 101000
using namespace std;
int sum1,sum2;
int t,n,sum,tot,anss;
int out[30],into[30];
string s[MAXN],ans[MAXN];
int fa[30],vi[MAXN],vis[30],num[MAXN];
int to[MAXN],net[MAXN],head[MAXN];
void add(int u,int v){
    to[++tot]=v;net[tot]=head[u];head[u]=tot;
}
int cmp(string a,string b){
    return a<b;
}
int find(int x){
    if(fa[x]==x)    return fa[x];
    return fa[x]=find(fa[x]);
}
void dfs(int now,int id){
    for(int i=head[now];i;i=net[i])
        if(!vi[i]){
            vi[i]=1;
            dfs(to[i],i);
        }
    if(id!=-1)    ans[++anss]=s[id];
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        sum=sum1=sum2=0;tot=0;
        memset(to,0,sizeof(to));
        memset(net,0,sizeof(net));
        memset(vis,0,sizeof(vis));
        memset(out,0,sizeof(out)); 
        memset(head,0,sizeof(head));
        memset(into,0,sizeof(into));
        for(int i=1;i<=26;i++)    fa[i]=i;
        for(int i=1;i<=n;i++)    cin>>s[i];
        sort(s+1,s+1+n,cmp);
        for(int i=1;i<=n;i++){
            int x=s[i][0]-'a'+1;
            int y=s[i][s[i].length()-1]-'a'+1;
            out[x]++;   into[y]++;
            vis[x]=1;    vis[y]=1;
            add(x,y);
            int dx=find(x); int dy=find(y);
            if(dx!=dy)    fa[dy]=dx;
        }
        for(int i=1;i<=26;i++)
            if(vis[i]&&fa[i]==i)    sum++;
        if(sum>1){ cout<<"***"<<endl;continue; }    sum=0;
        for(int i=1;i<=26;i++)
            if(vis[i]&&into[i]!=out[i]){
                sum++;
                if(into[i]-1==out[i])    sum1=i;
                if(into[i]==out[i]-1)    sum2=i;
            }
        if(sum==0){
            for(int i=1;i<=26;i++)
                if(vis[i]){ dfs(i,-1);break; }
        }
        else if(sum1&&sum2&&sum==2)    dfs(sum2,-1);
        else{ cout<<"***"<<endl;continue; }
        cout<<ans[anss];
        for(int i=anss-1;i>=1;i--)
            cout<<"."<<ans[i];
        cout<<endl;
    }
}
 
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/8092854.html