思路:把每个单词看做一条边,就变成了在有向图上判断是否存在一个欧拉道路,词头要被词尾连接,所以是入度。注意:
欧拉图的定义:有向图满足欧拉道路的条件就是:1.连通.2.图中入度不等于出度的点最多两个, 一个入度 = 出度 + 1,另一个入度 + 1 = 出度。代码来自: https://blog.csdn.net/u011345461/article/details/9314713
1 #include<stdio.h>
2 #include<string.h>
3 #define N 1050
4 int map[N][N], in[N], out[N], vis[N];
5 int n, m;
6
7 void dfs(int u)
8 {
9 vis[u] = 1;
10 for (int i = 0; i < N; i++)
11 if (!vis[i] && map[u][i])//在图中且没有被搜过的点
12 dfs(i);
13 }//深搜,将点连通
14
15
16 int main() {
17
18 scanf("%d", &n);
19
20 while (n--) {
21
22 char str[1050];
23
24 scanf("%d", &m);
25 memset(map, 0, sizeof(map));
26 memset(in, 0, sizeof(in));
27 memset(out, 0, sizeof(out));
28
29 for (int i = 0; i < m; i++) {
30
31 scanf("%s", &str);
32
33 map[str[strlen(str) - 1] - 'a'][str[0] - 'a']++;
34 out[str[strlen(str) - 1] - 'a']++;//词末字母是出度加一
35 in[str[0] - 'a']++;//词头是入度
36
37
38 }
39
40 int num1 = 0, num2 = 0;
41 int flag1 = 1, flag2 = 1;
42
43 //判断奇数点的个数,与是否都是偶数点
44 for (int i = 0; i < N; i++)
45 {
46 if (flag1 == 0)
47 break;
48 if (out[i] != in[i])
49 if (in[i] == out[i] + 1)//出入度不一样,数奇数点的个数
50 {
51 num1++;
52 }
53 else if (out[i] == in[i] + 1)
54 {
55 num2++;
56 }
57 else//不符合奇数点的条件
58 {
59 flag1 = 0;
60 break;
61 }
62 }
63
64 if (num1 && num2 && num1 + num2 > 2) //奇数点个数大于2
65 flag1 = 0;
66
67 if (flag1) {
68
69 memset(vis, 0, sizeof(vis));
70 for (int i = 0; i < N; i++)
71 if (in[i])
72 {
73 dfs(i);
74 break;
75 }
76
77 //判断是否有度数的点都有遍历到
78 for (int i = 0; i < N; i++)
79 {
80 if (in[i] && !vis[i])
81 {
82 flag2 = 0;
83 break;
84 }
85 if (out[i] && !vis[i])
86 {
87 flag2 = 0;
88 break;
89 }
90 }
91
92 if (flag2)
93 printf("Ordering is possible.\n");
94 else
95 printf("The door cannot be opened.\n");
96 }
97 else
98 printf("The door cannot be opened.\n");
99
100 }
101
102 return 0;
103 }