1 /*
2 题意:给出N个单词,一个单词的头字母和另一个单词的尾字母相同则可以相连,问这N个单词是否能完全相连成一行
3
4 题解:求欧拉路径
5 首先以每个单词的首字母和尾字母为点并且连边,然后用DFS求该图是否连通,然后根据点的入度和出度判断是否存在
6 欧拉路径或者欧拉回路(存在回路也是符合要求的)
7 */
8 #include <cstdio>
9 #include <cstring>
10
11 int map[30][30];
12 int in[30],out[30];
13
14 bool exist[30],vis[30];
15
16 void dfs(int u)
17 {
18 vis[u] = true;
19 for(int i=0; i<26; i++)
20 if (map[u][i] && exist[i] && !vis[i])
21 dfs(i);
22 }
23
24 int main(void)
25 {
26 int t;
27 scanf("%d",&t);
28 char str[1005];
29 while (t--)
30 {
31 int n;
32 scanf("%d",&n);
33 memset(map,0,sizeof(map));
34 memset(in,0,sizeof(in));
35 memset(out,0,sizeof(out));
36 memset(exist,false,sizeof(exist));
37
38 for(int i=0; i<n; i++)
39 {
40 scanf("%s",str);
41 int len = strlen(str);
42 int u = str[0]-‘a‘, v = str[len-1]-‘a‘;
43 map[u][v]++;
44 in[v] ++;
45 out[u] ++;
46 exist[u] = exist[v] = true;
47 }
48
49
50 // 找出合适的起点进行DFS,入度小于出度的肯定是起点,要么就任意起点
51 memset(vis,false,sizeof(vis));
52 int i;
53 for(i=0; i<26; i++)
54 if (exist[i])
55 break;
56 for(int j=i+1; j<26; j++)
57 if (exist[j] && in[j] < out[j])
58 {
59 i = j;
60 break;
61 }
62 dfs(i);
63 for(i=0; i<26; i++) // 连通则所有点都遍历了
64 if (exist[i] && !vis[i])
65 break;
66
67 bool flag = false;
68 if (i >= 26)
69 {
70 int head = 0,tail = 0,mid = 0, sum = 0;
71 for(int i=0; i<26; i++)
72 {
73 if (exist[i])
74 {
75 sum++;
76 if (in[i] == out[i])
77 mid++;
78 if (in[i] - out[i] == -1)
79 head++;
80 if (in[i] - out[i] == 1)
81 tail++;
82 }
83 }
84 if (sum == mid || (head == 1 && tail == 1 && mid == sum-2)) // 判断欧拉路径或回路
85 flag = true;
86 }
87
88 if (flag)
89 printf("Ordering is possible.\n");
90 else
91 printf("The door cannot be opened.\n");
92 }
93 return 0;
94 }
poj 1386 欧拉路径
时间: 2024-11-07 04:41:45