You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.3 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, M = 100010;
int m;
int din[N], dout[N];
int cnt;
// 链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
// 欧拉通路+删边优化+边记数
void dfs(int u) {
for (int i = h[u]; ~i; i = h[u]) {
h[u] = ne[i];
dfs(e[i]);
cnt++;
}
}
int main() {
char str[N]; // char数组的性能比string要强建议使用此方法
int T;
scanf("%d", &T);
while (T--) {
memset(h, -1, sizeof h);
idx = cnt = 0;
memset(din, 0, sizeof din);
memset(dout, 0, sizeof dout);
scanf("%d", &m);
for (int i = 0; i < m; i++) {
scanf("%s", str); // 配合字符数组完成字符串读入
int a = str[0] - 'a', b = str[strlen(str) - 1] - 'a';
add(a, b); // 有向图建边
din[b]++, dout[a]++;
}
// 枚举每个字母映射的节点0~25
int start = 0, s = 0, e = 0; // start:起点s:起点个数,e:终点个数
for (int i = 0; i < 26; i++)
if (din[i] != dout[i]) { // 如果入度与出度不相等,那么必须是一个起点,一个终点
if (din[i] == dout[i] - 1) // 入度=出度-1 ->起点
start = i, s++; // 记录起点
else if (din[i] == dout[i] + 1) // 入度=出度+1 ->终点
e++;
else { // 没有欧拉通路,标识start=-1,表示检查失败
start = -1;
break;
}
}
// start==-1 : 不存在欧拉路径
// s> 1 || e>1 : 起点数量大于1或者终点数量大于1
if (start == -1 || s > 1 || e > 1) {
puts("The door cannot be opened.");
continue;
}
// 用dfs判断是否连通,用上面的欧拉定理先把度的事处理完再dfs可以提速
dfs(start);
// 如果枚举到的边数小于图中的边,表示没走全,说明图不连通
if (cnt < m)
puts("The door cannot be opened.");
else
puts("Ordering is possible.");
}
return 0;
}