Catenyms
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 8505 | Accepted: 2237 |
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:
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.
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 ***
题意:给出n个单词,若一个单词的末尾字母和另一个单词的首字母相同,则它们可以连在一起。问是否能将这n个单词都连成一串序列,若能,输出字典序最小的序列。
思路:将每个单词的首字母和末尾字母分别看出一个点,单词看成是边,转化为求有向图的欧拉路径。有向图的欧拉路径存在的充要条件为所有点的出度==入度,或有一个点的出度-入度=1且有一个点的入度-出度=1。判断完是否存在欧拉路径后,就对单词进行排序,这里用邻接表排序。最后进行dfs,若所有点的出度==入度,则从字典序最小的点开始dfs,否则,从出度-入度=1的点开始dfs。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <cmath> #include <map> #include <cstdlib> #define L(rt) (rt<<1) #define R(rt) (rt<<1|1) #define ll long long #define eps 1e-6 using namespace std; const int maxn=1005; struct node { int v; bool vis; char str[25]; } edge; vector<node>G[30]; stack<char *>print; int in[30],out[30],fa[30],st; bool vis[30]; int n; bool cmp(node a,node b) { return strcmp(a.str,b.str)<0; } void init() { memset(vis,false,sizeof(vis)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); for(int i=0; i<30; i++) { fa[i]=i; G[i].clear(); } st=-1; } int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } void Union(int a,int b) { fa[find(a)]=find(b); } bool judge() { int cnt=0; for(int i=0; i<26; i++) if(vis[i]&&fa[i]==i) cnt++; if(cnt>1) return false; int cnt1=0,cnt2=0; for(int i=0; i<26; i++) if(vis[i]) { if(in[i]==out[i]) continue; else if(in[i]-out[i]==1) cnt1++; else if(out[i]-in[i]==1) { cnt2++; st=i; } else return false; } if((cnt1==0&&cnt2==0)||(cnt1==1&&cnt2==1)) return true; return false; } void dfs(int u) { for(int i=0;i<(int)G[u].size();i++) { int v=G[u][i].v; if(!G[u][i].vis) { G[u][i].vis=true; dfs(v); print.push(G[u][i].str); } } } int main() { int t; scanf("%d",&t); while(t--) { init(); scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%s",edge.str); int len=strlen(edge.str); int a=edge.str[0]-'a'; int b=edge.str[len-1]-'a'; vis[a]=vis[b]=true; edge.v=b; edge.vis=false; G[a].push_back(edge); out[a]++; in[b]++; Union(a,b); } if(!judge()) { printf("***\n"); continue; } for(int i=0; i<26; i++) if(vis[i]) sort(G[i].begin(),G[i].end(),cmp); if(st==-1) { for(int i=0; i<26; i++) if(vis[i]) { dfs(i); break; } } else dfs(st); char *s=print.top(); print.pop(); printf("%s",s); while(!print.empty()) { s=print.top(); print.pop(); printf(".%s",s); } puts(""); } return 0; }