[POJ2337]Catenyms

Posted skylee的OI博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POJ2337]Catenyms相关的知识,希望对你有一定的参考价值。

题目大意:
  定义一个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 }

 

以上是关于[POJ2337]Catenyms的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2337 Catenyms

[POJ2337]Catenyms

Catenyms (POJ2337) 字典序最小欧拉路

POJ 2337 Catenyms(有向欧拉图:输出欧拉路径)

POJ 2337 欧拉路

poj 2337(单向欧拉路的判断以及输出)