题目大意:
定义一个catenym是一对单词,满足第一个单词的末尾字符与第二个单词的开头字符相等。
定义复合catenym是一些单词,满足第i个单词的末尾字符与第i+1个单词的开头字符相等。
给你n个字符串,判断它们是否能构成复合catenym。
如果能,求出字典序最小的那个catenym。
思路:
以字母为点,单词为边建图。用类似Fleury算法,跑一边欧拉路径,如果能跑出欧拉路经则说明可以构成。
为了保证catenym的字典序最小,我们就要保证在Fleury的时候,按照字典序遍历。
因此我们要先对所有的单词按字典序排序,然后加边。
1 */ 2 #include<stack> 3 #include<string> 4 #include<vector> 5 #include<iostream> 6 #include<algorithm> 7 #include<functional> 8 const int N=1000,V=26; 9 std::string s[N]; 10 struct Edge { 11 int to,id; 12 bool vis; 13 }; 14 std::vector<Edge> e[V]; 15 inline void add_edge(const int &u,const int &v,const int &i) { 16 e[u].push_back((Edge){v,i,false}); 17 } 18 inline int idx(const int &ch) { 19 return ch-'a'; 20 } 21 bool vis[V]; 22 int in[V],out[V]; 23 std::stack<int> ans; 24 void dfs(const int &x) { 25 for(std::vector<Edge>::reverse_iterator i=e[x].rbegin();i!=e[x].rend();i++) { 26 if(i->vis) continue; 27 i->vis=true; 28 dfs(i->to); 29 ans.push(i->id); 30 } 31 } 32 inline void init() { 33 for(register int i=0;i<V;i++) e[i].clear(); 34 std::fill(&in[0],&in[V],0); 35 std::fill(&out[0],&out[V],0); 36 std::fill(&vis[0],&vis[V],false); 37 while(!ans.empty()) ans.pop(); 38 } 39 int main() { 40 std::ios_base::sync_with_stdio(false); 41 std::cin.tie(NULL); 42 register int T; 43 for(std::cin>>T;T;T--) { 44 init(); 45 int n; 46 std::cin>>n; 47 for(register int i=0;i<n;i++) { 48 std::cin>>s[i]; 49 } 50 std::sort(&s[0],&s[n],std::greater<std::string>()); 51 int start=V; 52 for(register int i=0;i<n;i++) { 53 const int &u=idx(*s[i].begin()),&v=idx(*--s[i].end()); 54 out[u]++; 55 in[v]++; 56 add_edge(u,v,i); 57 start=std::min(start,std::min(u,v)); 58 } 59 int cnts=0,cntt=0; 60 bool flag=false; 61 for(register int i=0;i<V;i++) { 62 if(out[i]-in[i]==1) { 63 cnts++; 64 start=i; 65 } else if(in[i]-out[i]==1) { 66 cntt++; 67 } else if(in[i]!=out[i]){ 68 flag=true; 69 } 70 } 71 if(flag||!((cnts==0&&cntt==0)||(cnts==1&&cntt==1))) { 72 std::cout<<"***"<<std::endl; 73 continue; 74 } 75 dfs(start); 76 if((signed)ans.size()!=n) { 77 std::cout<<"***"<<std::endl; 78 continue; 79 } 80 std::cout<<s[ans.top()]; 81 ans.pop(); 82 while(!ans.empty()) { 83 std::cout<<'.'<<s[ans.top()]; 84 ans.pop(); 85 } 86 std::cout<<std::endl; 87 } 88 return 0; 89 }