题目的大意是:给出一些单词,问能否拼接成一串,使单词字母首尾相连。
例如,Sample中的:
acm
malform
mouse
我们可以构造出:
acm->malform->mouse,符合题目要求。
/*
1. 有向图G为欧拉图,当且仅当G的基图 连通,且所有顶点的入度等于出度。
2. 有向图G为半欧拉图,当且仅当G的基图连通,且存在一个顶点的入度比出度大1,
一个顶点入度比出度小1,其它所有顶点的入度等于出度。
3. 无向图G为欧拉图,当且仅当G为连通的,且所有顶点度为偶数或者度为奇数的顶点个数为0或者2
4. 图的连通性可用并查集判断
*/
#include <iostream>
using namespace std;
const int MAX_LEN = 1002;
const int ALPHA_NUM = 26;
int degree[ALPHA_NUM], father[ALPHA_NUM];
char word[MAX_LEN];
int find_set(int i)
{
if (i != father[i]){
father[i] = find_set(father[i]);
}
return father[i];
// while (i != father[i]){
// i = father[i];
// }
// return father[i];
}
void make_set(int i)
{
if (-1 == father[i]) father[i] = i;
}
void union_set(int a, int b)
{
a = find_set(a);
b = find_set(b);
if (a != b){
father[a] = b;
// if (rank[a] == rank[b]){
// father[a] = b;
// rank[a]++;
// }
// else if (rank[a] < rank[b]){
// father[a] = b;
// }
// else{
// father[b] = a;
// }
}
}
int main()
{
int c, n, i, j, len;
scanf("%d", &c);
for (i = 0; i < c; ++i){
memset(degree, 0, sizeof(degree));
memset(father, -1, sizeof(father));
scanf("%d", &n);
for (j = 0; j < n; ++j){
scanf("%s", word);
len = strlen(word);
int a = word[0] - 'a';
int b = word[len-1] - 'a';
degree[a]++;
degree[b]--;
make_set(a);
make_set(b);
union_set(a, b);
}
int ne = 0, ng = 0, nl = 0;
for (j = 0; j < ALPHA_NUM; ++j){
if (degree[j] == 1){
ng++;
}
else if (degree[j] == -1){
nl++;
}
else if (degree[j] == 0){
ne++;
}
}
if (!((ng == 1 && nl == 1 && ne == ALPHA_NUM - 2) //欧拉通路
|| ne == ALPHA_NUM)){ //欧拉回路
printf("The door cannot be opened.\n");
continue;
}
for (j = 0; father[j] == -1; ++j);
int root = find_set(j);
for (j = j+1; j < ALPHA_NUM; ++j){
if (father[j] == -1) continue;
if (find_set(j) != root){ //所有的节点都有相同的祖先,则图是连通的
printf("The door cannot be opened.\n");
break;
}
}
if (j == ALPHA_NUM){
printf("Ordering is possible.\n");
}
}
}