思路: 欧拉回路
分析:
1 题目给定n个字符串,判断是否可以按照题目的要求可以组成一个长串
2 很明显题目是要求有向图是否有欧拉回路或者是欧拉道路
3 首先我们先判断有向图是否是单连通,那么这里面我们可以用并查集去求单连通性
4 如果是单连通的话,我们知道对于有向图来说如果存在欧拉道路的话那么最多有两个点的入度不等于长度并且入度和出度的绝对值为1,其它所有点的入度等于出度
5 注意n=1的时候都认为是可以满足条件
代码:
#include<set>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 30;
int n , inDegree[N] , outDegree[N];
int mat[N][N] , father[N];
bool vis[N];
void init(){
memset(vis , false , sizeof(vis));
memset(inDegree , 0 , sizeof(inDegree));
memset(outDegree , 0 , sizeof(outDegree));
memset(mat , 0 , sizeof(mat));
for(int i = 0 ; i < N ; i++)
father[i] = i;
}
int find(int x){
if(father[x] != x)
father[x] = find(father[x]);
return father[x];
}
bool isOk(){
set<int>s;
for(int i = 0 ; i < N ; i++)
if(vis[i])
s.insert(find(i));
if(s.size() > 1)//如果有多个连通分支即不满足
return false;
int cnt = 0;
for(int i = 0 ; i < N ; i++){
if(abs(inDegree[i]-outDegree[i]) > 1) //如果绝对值大于1则不满足
return false;
if(abs(inDegree[i]-outDegree[i]) == 1)
cnt++;
}
return cnt <= 2;//最多2个点的出度和入度绝对值为1
}
int main(){
int Case , x , y;
char str[1010];
scanf("%d" , &Case);
while(Case--){
scanf("%d" , &n);
init();
for(int i = 0 ; i < n ; i++){
scanf("%s" , str);
x = str[0]-'a';
y = str[strlen(str)-1]-'a';
vis[x] = vis[y] = true;
inDegree[y]++;
outDegree[x]++;
mat[x][y]++;
father[find(x)] = find(y);
}
if(n == 1 || isOk())
puts("Ordering is possible.");
else
puts("The door cannot be opened.");
}
return 0;
}