/*
* poj1386.cpp
*
* Created on: 2010-8-13
* Author: friendy
*/
//并查集加欧拉路
#include
#include
#include
using namespace std;
char s[1001];
int f[27], rank[27];
int flag[26], mark[26];
int n;
//并查集判连通
void Init() {
memset(flag, 0, sizeof(flag));
memset(mark, 0, sizeof(mark));
int i;
for (i = 0; i < 26; i++) {
f[i] = i;
rank[i] = 0;
}
}
int Find(int x) {
if (x != f[x])
f[x] = Find(f[x]);
return f[x];
}
void Union(int i, int j) {
int x = Find(i);
int y = Find(j);
if (x == y)
return;
if (rank[x] > rank[y])
f[y] = x;
else {
f[x] = y;
if (rank[x] == rank[y])
rank[y]++;
}
}
int solve() {
int i;
int cnt = 0;
for (i = 0; i < 26; i++) {//是否连通,看看出现的字母是不是在同一个集合中
if (mark[i]) {
if (f[i] == i)
cnt++;
if (cnt > 1)
return 0;
}
}
int cnt1 = 0, cnt2 = 0;
for (i = 0; i < 26; i++) {//判断是否是欧拉路或者回路
if (mark[i]) {
if (flag[i] > 1 || flag[i] < -1)
return 0;
if (flag[i] == 1)
cnt1++;
if (flag[i] == -1)
cnt2++;
if (cnt1 > 1 || cnt2 > 1)
return 0;
}
}
if (cnt1 ==cnt2)//注意这里不能写成二者都为1,也可能同时为0,前者是欧拉路后者是欧拉回路
return 1;
return 0;
}
int main() {
int i, t;
int ch1, ch2;
scanf("%d", &t);
while (t--) {
Init();
scanf("%d", &n);
getchar();
for (i = 0; i < n; i++) {
gets(s);
ch1 = s[0] - 'a';
flag[ch1]++;
ch2 = s[strlen(s) - 1] - 'a';
flag[ch2]--;
Union(ch1, ch2);
mark[ch1] = mark[ch2] = 1;//注意要标记一下使用的字母
}
if (solve()) {
printf("Ordering is possible./n");
} else {
printf("The door cannot be opened./n");
}
}
}
poj1386
最新推荐文章于 2021-05-14 23:51:02 发布