把每个单词的第一个和最后 一个字符作为一条有向边,26个字母作为节点构造有向图,如果该图中存在欧拉回路或者欧拉路,就符合题设要求,反之不符合要求,可以先用并查集判断有向图是不是弱连通的,然后把所有入度等于出度的点取出来,如果取出来的点的个数为0,说明存在欧拉回路,如果取出来的点的个数不等于0也不等于2,肯定没有欧拉路存在了,如果取出来的点的个数等于2,还要判断这两个点的入度和出度,是不是一个入度比出度大1,另一个入度比出度小1,是的话那么将这两个点作为起始点和结束点,可以形成一条欧拉路,否则不存在欧拉路。
#include <stdio.h>
#include <set>
#include <algorithm>
#include <string.h>
using namespace std;
int my_set[26]; //并查集
int set_len[26];
set<char> s;
char buffer[1005];
struct node
{
int in_degree;
int out_degree;
};
struct node degree[26];
void init_set()
{
for(int i=0; i<26; i++)
{
my_set[i] = i;
set_len[i] = 1;
degree[i].in_degree = degree[i].out_degree = 0;
}
}
int find_root(int i)
{
int root;
int p;
int root_temp;
root = i;
while(my_set[root] != root)
root = my_set[root];
p = i;
while(1)
{
root_temp = my_set[p];
my_set[p] = root;
p = root_temp;
if(my_set[p] == root)
break;
}
return root;
}
void merge(int i, int j)
{
int root_a, root_b;
root_a = find_root(i);
root_b = find_root(j);
if(root_a == root_b)
return;
my_set[root_a] = root_b;
set_len[root_b] += set_len[root_a];
set_len[root_a] = 0;
}
void func()
{
if(set_len[find_root(buffer[0]-'a')] != s.size()) //图不联通
{
printf("The door cannot be opened.\n");
return;
}
set<char> ss;
set<char>::iterator it;
for(it=s.begin(); it!=s.end(); it++)
{
if(degree[*it-'a'].in_degree != degree[*it-'a'].out_degree)
{
ss.insert(*it);
}
}
if(ss.size() == 0) //欧拉回路
{
printf("Ordering is possible.\n");
return;
}
if(ss.size() != 2) //不存在欧拉路
{
printf("The door cannot be opened.\n");
return;
}
if(ss.size()==2)
{
char ch1, ch2;
ch1 = *ss.begin();
ch2 = *(++ss.begin());
//判断是否存在欧拉路
if( degree[ch1-'a'].in_degree- degree[ch1-'a'].out_degree==1 && degree[ch2-'a'].in_degree- degree[ch2-'a'].out_degree==-1 )
{
printf("Ordering is possible.\n");
return;
}
if( degree[ch1-'a'].in_degree- degree[ch1-'a'].out_degree==-1 && degree[ch2-'a'].in_degree- degree[ch2-'a'].out_degree==1 )
{
printf("Ordering is possible.\n");
return;
}
}
printf("The door cannot be opened.\n");
}
int main(void)
{
int N, i, j, n;
//freopen("input.dat", "r", stdin);
scanf("%d", &N);
for(i=1; i<=N; i++)
{
scanf("%d", &n);
s.clear();
init_set();
for(j=1; j<=n; j++)
{
scanf("%s", buffer);
s.insert(buffer[0]);
s.insert(buffer[strlen(buffer)-1]);
degree[buffer[0]-'a'].out_degree++;
degree[buffer[strlen(buffer)-1]-'a'].in_degree++;
merge(buffer[0]-'a', buffer[strlen(buffer)-1]-'a');
}
func();
}
return 0;
}