第一次接触欧拉路,看了大神的解题报告后写出
并查集+欧拉回路,先要用并查集判断是否连通,然后再根据每个节点的入度与出度判断是否为欧拉回路或欧拉路
如果所有点入度等于出度,则为欧拉回路
如果起点的入度比出度小一且终点的入度比出度大一,则为欧拉路
#include <iostream> #include <cstring> using namespace std; #ifndef ONLINE_JUDGE #include <fstream> ifstream fin("test.txt"); #define cin fin #endif int p[27],vis[27],in[27],out[27]; int find(int r) //刚开始竟然把这里返回值设为bool,脑残了,找了半天找不到错 { return r == p[r] ? r : p[r] = find(p[r]); } void ini() { int i; for(i = 0; i < 26; ++i) p[i] = i; memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(vis,0,sizeof(vis)); } int main() { ios::sync_with_stdio(false); int t,n; string str; cin >> t; while(t--) { ini(); cin >> n; while(n--) { cin >> str; int l = str.length(); int a = str[0] - 'a',b = str[l-1] - 'a'; out[a]++; in[b]++; vis[a] = vis[b] = 1; int x = find(a); int y = find(b); if(x != y) p[y] = x; } int cnt = 0; for(int i = 0; i < 26; ++i) if(vis[i] && p[i] == i) cnt++; if(cnt > 1) { cout << "The door cannot be opened." << endl; continue; } int i,j = 0; for(i = 0; i < 26; ++i) if(in[i] != out[i] && vis[i]) str[j++] = i; if(!j) { cout << "Ordering is possible." << endl; } else { if(j == 2 && (in[str[0]] - out[str[0]] == 1 && out[str[1]] - in[str[1]] == 1 || in[str[1]] - out[str[1]] == 1 && out[str[0]] - in[str[0]] == 1)) cout << "Ordering is possible." << endl; else cout << "The door cannot be opened." << endl; } } return 0; }