Problem C: 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 first letter of the second. For example, the following are catenyms:dog.gopher gopher.rat rat.tiger aloha.aloha arachnid.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. 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. 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
Output for Sample Input
aloha.arachnid.dog.gopher.rat.tiger ***
首尾字符相同的单词可以连起来,输出字典序最小的序列把所有串都连起来,如果不能连起来输出***。
看着不难还做了好久。。
欧拉通路:如果图中存在一条通过图中各边一次且仅一次的通路,则称此回路是欧拉通路。有向图欧拉通路判断条件是:图连通,一个点入度比出度大1,另一个点出度比入度大1,或者所有点出度等于入度。
那么这里把字母当成点,单词当成边判断是否是欧拉通路就行,注意先判连通性。有一个问题是输出,我刚开始一直按顺序搜,遇到就输出,这样是不对的。比如za,ac,am,ma,cb,像我那么做直接是ba,ac,cb,而实际应该是za,am,ma,ac,cb。所以搜的时候如果找不到下一条边了就把这条边存起来,最后倒着输出,因为前面判过是欧拉通路了,最后肯定就是答案。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
typedef pair<int,int> pii;
const int MAXN=1010;
const int MAXM=25;
const int MAXNODE=32;
const int LOGMAXN=50;
const int INF=0x3f3f3f3f;
int T,N,K;
int vis[MAXN],ans[MAXN],in[30],out[30],alpha[30],top;
char a[MAXN][MAXM];
vector<int> G[30];
vector<pii> G2[30];
void dfs1(int u){
vis[u]=1;
int len=G[u].size();
for(int i=0;i<len;i++){
int v=G[u][i];
if(!vis[v]) dfs1(v);
}
}
void dfs2(int u){
int len=G2[u].size();
for(int i=0;i<len;i++){
int e=G2[u][i].first;
if(!vis[e]){
vis[e]=1;
dfs2(G2[u][i].second);
ans[top++]=e;
}
}
}
int check(){
int cnt=0,ret=0;
for(int i=0;i<26;i++){
if(in[i]==out[i]) continue;
else if(out[i]-in[i]==1){
cnt++;
ret=i;
}
else if(in[i]-out[i]>1||out[i]-in[i]>1) return -1;
}
if(!cnt){
for(int i=0;i<26;i++) if(vis[i]){
ret=i;
break;
}
}
if(cnt<=1) return ret;
return -1;
}
bool cmp(pii A,pii B){
return strcmp(a[A.first],a[B.first])<0?true:false;
}
int main(){
freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d",&N);
K=0;
memset(out,0,sizeof(out));
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
memset(alpha,0,sizeof(alpha));
for(int i=0;i<26;i++){
G[i].clear();
G2[i].clear();
}
int n,c;
for(int i=1;i<=N;i++){
scanf("%s",a[i]);
int len=strlen(a[i]),u=a[i][0]-'a',v=a[i][len-1]-'a';
out[u]++;
in[v]++;
if(!alpha[u]){
K++;
c=u;
alpha[u]=1;
}
if(!alpha[v]){
K++;
c=v;
alpha[v]=1;
}
G[u].push_back(v);
G[v].push_back(u);
G2[u].push_back(make_pair(i,v));
}
int cnt=0;
dfs1(c);
for(int i=0;i<26;i++) if(vis[i]){
cnt++;
}
if(cnt==K) n=check();
else n=-1;
if(n==-1) printf("***\n");
else{
for(int i=0;i<26;i++) sort(G2[i].begin(),G2[i].end(),cmp);
memset(vis,0,sizeof(vis));
top=0;
dfs2(n);
for(int i=top-1;i>0;i--) printf("%s.",a[ans[i]]);
printf("%s\n",a[ans[0]]);
}
}
return 0;
}