Catenyms
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 8078 | Accepted: 2127 |
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 ***
思路:
欧拉回路:图G,若存在一条路,经过G中每条边有且仅有一次,称这条路为欧拉路,如果存在一条回路经过G每条边有且仅有一次,
称这条回路为欧拉回路。具有欧拉回路的图成为欧拉图。
判断欧拉路是否存在的方法
有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。
无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。
判断欧拉回路是否存在的方法
有向图:图连通,所有的顶点出度=入度。
无向图:图连通,所有顶点都是偶数度。
程序实现一般是如下过程:
1.利用并查集判断图是否连通,即判断p[i] < 0的个数,如果大于1,说明不连通。
2.根据出度入度个数,判断是否满足要求。
3.利用dfs输出路径。
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<stdio.h> 4 #include<string.h> 5 #include<math.h> 6 #include<queue> 7 #include<stack> 8 using namespace std; 9 10 11 struct Nod 12 { 13 int next; 14 int to; 15 char str[30]; 16 }node[1010]; 17 18 int parent[30]; 19 //下面数组分别为出度,入度,存在标记, 20 int in[30],out[30],existmark[30],used[1010],adj[30]; 21 22 stack<int> st; //保存最后的结果,倒序输出 23 24 //并查集1 25 int findp(int u) 26 { 27 while(u!=parent[u]) 28 { 29 u=parent[u]; 30 } 31 return u; 32 } 33 34 //并查集2 35 void unit(int u,int v) 36 { 37 int r1=findp(u); 38 int r2=findp(v); 39 if(r1==r2) 40 return ; 41 parent[r1]=r2; 42 } 43 44 //排序,字典序倒序 45 bool cmp(Nod p1, Nod p2) 46 { 47 return strcmp(p1.str, p2.str) > 0; 48 } 49 50 //初始化 51 void init() 52 { 53 int i; 54 for(i=0;i<26;i++) 55 parent[i]=i; 56 memset(in,0,sizeof(in)); 57 memset(out,0,sizeof(out)); 58 memset(existmark,0,sizeof(existmark)); 59 memset(used,0,sizeof(used)); 60 memset(adj,-1,sizeof(adj)); 61 } 62 //欧拉路 63 void Eular(int start,int pos) 64 { 65 int i; 66 for(i=adj[start];i!=-1;i=node[i].next) 67 { 68 if(!used[i]) 69 { 70 used[i]=1; 71 Eular(node[i].to,i); 72 } 73 } 74 if(0 <= pos) 75 st.push(pos); 76 } 77 78 int main() 79 { 80 int t; 81 scanf("%d",&t); 82 while(t--) 83 { 84 int n; 85 scanf("%d",&n); 86 init(); 87 int i,v,u; 88 for(i=0;i<n;i++) 89 { 90 scanf("%s",node[i].str); 91 } 92 sort(node, node + n, cmp); 93 for(i=0;i<n;i++) 94 { 95 u=node[i].str[0]-'a'; 96 v=node[i].str[strlen(node[i].str)-1]-'a'; 97 out[u]++; 98 in[v]++; 99 existmark[u]=1; 100 existmark[v]=1; 101 unit(u,v); 102 node[i].to=v; 103 node[i].next=adj[u]; 104 adj[u]=i; 105 // cout<<i<<" "<<u<<" "<<node[i].next<<endl; 106 } 107 108 int flag=0; 109 for(i=0;i<26;i++) 110 { 111 if(existmark[i]&&parent[i]==i) 112 flag++; 113 } 114 if(flag>1) 115 { 116 printf("***\n"); 117 continue; 118 } 119 120 int a=0,b=0,start=-1; 121 for(i=0;i<26;i++) 122 { 123 if(in[i]!=out[i]&&existmark[i]) 124 { 125 if(1==in[i]-out[i]) 126 { 127 a++; 128 }else if(1==out[i]-in[i]) 129 { 130 b++; 131 start=i; 132 }else 133 { 134 break; 135 } 136 } 137 } 138 if(i<26) 139 { 140 printf("***\n"); 141 continue; 142 }else 143 { 144 if(!((0 == a + b) || (1 == a && 1 == b))) 145 { 146 printf("***\n"); 147 continue; 148 } 149 //a+b==0或者1==a并且1==b时 150 if(-1==start) 151 { 152 for(i=0;i<26;i++) 153 { 154 if(out[i]) 155 break; 156 } 157 start=i; 158 } 159 Eular(start, -1); 160 //输出 161 printf("%s", node[st.top()].str); 162 st.pop(); 163 while(!st.empty()) 164 { 165 printf(".%s", node[st.top()].str); 166 st.pop(); 167 } 168 printf("\n"); 169 } 170 } 171 return 0; 172 }