Catenyms
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11648 | Accepted: 3036 |
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 ***
题意:给定一系列字符串,如果某个字符串的结尾和另外一个字符串的开头相等,那么两个字符串就可以拼接在一起,现在问所有的字符串能否刚好都出现一次?如果存在,输出字典序最小的那个组合.
题解:将字符串看成一条边,然后将其起始字符和结尾字符看成边的两个端点,构造一个有向图,然后就判断这个图是否为欧拉图了.判断单向欧拉图的方法:
有向欧拉通路:起点:出度-入度=1,终点:入度-出度=1,其它点:入度==出度
有向欧拉回路:所有点:入度==出度
还要利用并查集判断一下这个图是否只有一个连通分量.
然后将所有的边按照字典序排序,找到起点,进行DFS(Edge &e = edge[u][i] 这里检查了半天,一点要记得是地址啊...),即可得到答案.
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #include <vector> #include <stack> using namespace std; const int N = 2222; char str[100]; struct Edge{ char str[100]; int to,del; }; typedef vector <Edge> vec; stack <string> ans; vec edge[N]; int in[N],out[N],father[N]; bool vis[N],mark[30]; int n; void init(){ memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(vis,false,sizeof(vis)); for(int i=1;i<=30;i++){ mark[i] = false; edge[i].clear(); father[i] = i; } } int _find(int x){ return x==father[x]?x:father[x] = _find(father[x]); } void dfs(int u){ for(int i=0;i<edge[u].size();i++){ Edge &e = edge[u][i]; ///这里要取地址 int v = e.to; if(!e.del){ e.del = 1; dfs(v); ans.push(e.str); } } } bool cmp(Edge a,Edge b){ return strcmp(a.str,b.str)<0; } int main() { int tcase; scanf("%d",&tcase); while(tcase--){ init(); scanf("%d",&n); int S = N; for(int i=1;i<=n;i++){ scanf("%s",str); int s = str[0]-'a'+1; int t = str[strlen(str)-1]-'a'+1; Edge e; e.del = 0; strcpy(e.str,str); e.to = t; edge[s].push_back(e); in[t]++; out[s]++; mark[t] = mark[s] = 1; int u = _find(s); int v = _find(t); if(u!=v) father[u] = v; S = min(S,min(s,t)); } int num1 = 0,num2 = 0,num3 = 0,num4 = 0; for(int i=1;i<=26;i++){ if(mark[i]==1&&father[i]==i) num4++; if(out[i]-in[i]==1){ S = i; num1++; } else if(in[i]-out[i]==1){ num2++; }else if(in[i]-out[i]!=0){ num3++; } if(!edge[i].empty()) sort(edge[i].begin(),edge[i].end(),cmp); } if(num3||!(num1==1&&num2==1)&&!(num1==0&&num2==0)||num4>1){ printf("*** "); continue; } dfs(S); int flag = 0; while(!ans.empty()){ if(flag) printf("."); cout<<ans.top(); flag = 1; ans.pop(); } printf(" "); } }