跟Uva 10054很像,不過這題的單詞是不能反向的,所以是有向圖,判斷歐拉道路。
關於歐拉道路(from Titanium大神):
判斷有向圖是否有歐拉路
1.判斷有向圖的基圖(即有向圖轉化為無向圖)連通性,用簡單的DFS即可。如果圖都不連通,一定不存在歐拉路
2.在條件1的基礎上
對於歐拉回路,要求苛刻一點,所有點的入度都要等於出度,那麼就存在歐拉回路了
對於歐拉道路,要求松一點,只有一個點,出度比入度大1,這個點一定是起點; 一個點,入度比出度大1,這個點一定是終點.其余點的出度等於入度
(注意,只能大1,而且這樣的點分別只能有1個,而且存在起點就一定要存在終點,存在終點就一定要存在起點)
他用判斷連通性用的是DFS,我用的是並查集實現。
然後判斷為歐拉回路(入度=出度)或者歐拉道路(出入度相差1的點只有不同的兩個)(而且其他點出度=入度!)。
代碼:
#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; }