/* 把字母看作结点,单词看成有向边,则,问题有解,当且仅当图中有欧拉路径 存在欧拉道路的条件,见小白书 P169 判断连通的方法有两种: 1. DFS 2. 并查集 */
#include <iostream> #include <vector> #include <string> #include <cstring> using namespace std; const int N = 256; int used[N]; // 是否出现过 int deg[N]; // 度数 int pa[N]; int find ( int x ) { return pa[x] != x ? pa[x] = find (pa[x]) : x; } void init() //初始化数组,初始化并查集 { memset( used, 0, sizeof(used) ); memset( deg, 0, sizeof(deg) ); for (int ch = 'a'; ch <= 'z'; ch++) pa[ch] = ch; } int main() { int t; cin >> t; while (t--) { int n; string word; cin >> n; init(); int cc = 26; // 连通块个数 for (int i = 0; i < n; i++) { cin >> word; char c1 = word[0], c2 = word[ (int)word.size() - 1]; deg[c1]++; deg[c2]--; used[c1] = used[c2] = 1; int s1 = find(c1), s2 = find(c2); if (s1 != s2) { pa[s1] = s2; cc--; } } vector<int> v; for (int ch = 'a'; ch <= 'z'; ch++) { if (!used[ch]) cc--; //没出现过的字母 else if (deg[ch] != 0) v.push_back(deg[ch]); } bool ok = false; if ( cc == 1 && ( v.empty() || ( v.size() == 2 && ( v[0] == 1 || v[0] == -1) ) ) ) ok = true; if (ok) cout << "Ordering is possible."; else cout << "The door cannot be opened."; cout << endl; } }