This is very similar to that of the WordPress 10054, but the words in this question cannot be reversed. Therefore, it is a directed graph to determine the Euler's path.
About Euler's Road (from Titanium ):
Determine whether a directed graph has an Euler's path.
1. Determine the connectivity of the base graph of the directed graph (that is, converting the directed graph to an undirected graph). Use a simple DFS. If no graph is connected, there must be no Euler's path.
2. Based on condition 1
For the Euler loop, the requirements are harsh. The inbound degree of all points must be equal to the outbound degree, so there is an Euler loop.
For the Euler's road, it is required to be loose. There is only one point, and the outbound value is 1 higher than the inbound value. This point must be the starting point. One point, the inbound value is 1 larger than the outbound value, this point must be the end point. the outbound value of other points is equal to the inbound value.
(Note: The value can only be 1 larger, and there can be only one such point, and there must be an end point if there is a start point, and there must be a start point if there is an end point)
He uses DFS to determine connectivity, and I use and query set implementation.
Then it is determined to be an Euler Loop (inbound = outbound) or an Euler Road (only two points with a 1 difference in inbound and outbound degree) (and other points exit = inbound degree !).
Code:
#include <cstdio> #include <cstdlib> #include <cstring> const int maxn = 30; int f[maxn], g[maxn][maxn], id[maxn], od[maxn]; int t, n, root; int Find(int x) { if (x != f[x]) return f[x] = Find(f[x]); return x; } int main () { scanf("%d", &t); while (t--) { char word[1001]; scanf("%d", &n); for (int i = 0; i < maxn; i++) { f[i] = i; id[i] = 0; od[i] = 0; for (int j = 0; j < maxn; j++) g[i][j] = 0; } for (int i = 0; i < n; i++) { scanf("%s", word); int a = word[0] - 'a', b = word[strlen(word) - 1] - 'a'; g[a][b]++; od[a]++; id[b]++; f[Find(a)] = Find(b); root = Find(b); } int i, ans = 0, flag = 1, in = 0, on = 0; for (i = 0; i < maxn; i++) if (id[i] || od[i]) { if (Find(f[i]) != root) ans++; if (id[i] - od[i] == 1) in++; else if (od[i] - id[i] == 1) on++; else if (abs(id[i] - od[i]) > 1) break; } // printf("%d %d %d %d\n", i, ans, in, on); if (i < maxn || ans > 0 || in > 1 || on > 1) printf("The door cannot be opened.\n"); else printf("Ordering is possible.\n"); }//while return 0; } #include <cstdio>#include <cstdlib>#include <cstring>const int maxn = 30;int f[maxn], g[maxn][maxn], id[maxn], od[maxn];int t, n, root;int Find(int x) { if (x != f[x]) return f[x] = Find(f[x]); return x;}int main () { scanf("%d", &t); while (t--) { char word[1001]; scanf("%d", &n); for (int i = 0; i < maxn; i++) { f[i] = i; id[i] = 0; od[i] = 0; for (int j = 0; j < maxn; j++) g[i][j] = 0; } for (int i = 0; i < n; i++) { scanf("%s", word); int a = word[0] - 'a', b = word[strlen(word) - 1] - 'a'; g[a][b]++; od[a]++; id[b]++; f[Find(a)] = Find(b); root = Find(b); } int i, ans = 0, flag = 1, in = 0, on = 0; for (i = 0; i < maxn; i++) if (id[i] || od[i]) { if (Find(f[i]) != root) ans++; if (id[i] - od[i] == 1) in++; else if (od[i] - id[i] == 1) on++; else if (abs(id[i] - od[i]) > 1) break; }// printf("%d %d %d %d\n", i, ans, in, on); if (i < maxn || ans > 0 || in > 1 || on > 1) printf("The door cannot be opened.\n"); else printf("Ordering is possible.\n"); }//while return 0;}