本来是一个非常简单的问题。就是先看是否联通,然后再根据节点数量来进一步判断。。。因为失了智所以又很多BUG,慢慢调
1.用op和ed来储存起点和终点。最多各有一个。
2.用一个exist数组来储存出现过的字符。
3.基础的dfs来遍历这个图。注意,因为这个是一个有向图,起点有两个要求。①入度比出度小1.②如果没有这种节点,那么就选择一个入度等于出度的节点。
4.再用书上的节点度的判断。
5.还有很多优化空间,但是不想做了。。。。
6.判断连通图的并查集和bfs方法也可以写一下。
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100000+5;
int edge[26][26];
int vis[26]={0};
int exist[26]={0};
void dfs(int u){//给u设置为1,并且遍历之后的节点
vis[u]=1;
for(int i=0;i<26;i++){
if(edge[u][i]&&!vis[i]){
dfs(i);
}
}
}
bool judge(){
for(int i = 0;i<26;i++){
if(exist[i]&&!vis[i]){
return false;
}
}
return true;
}
int main(void){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
int in[26]={0},out[26]={0};
memset(edge,0,sizeof(edge));
memset(vis,0,sizeof(edge));
memset(exist,0,sizeof(edge));
for(int i=0;i<n;i++){
char word[1005];
scanf("%s",word);
int from=word[0]-'a';
int to=word[strlen(word)-1]-'a';
edge[from][to]=1;
exist[from]=1;
exist[to]=1;
out[from]++;
in[to]++;
}
int start=-1,rando;
for(int i=0;i<26;i++){
if(out[i]-in[i]==1)
start=i;
if(exist[i]&&in[i]==out[i])//
rando=i;
}
// printf("%d\t%d\n",start,rando);
if(start!=-1){
dfs(start);
}
else{
dfs(rando);
}
if(judge())
{
// printf("judgeok\n");
int ok=1,op=0,ed=0;
for(int i=0;i<26;i++){
if(in[i]-out[i]>1) ok=0;
if(out[i]-in[i]>1) ok=0;
if(in[i]-out[i]==1){
ed++;
continue;
}
if(out[i]-in[i]==1){
op++;
continue;
}
}
if(op<=1&&ed<=1&&ok){
printf("Ordering is possible.\n");
}
else{
printf("The door cannot be opened.\n");
}
}
else{
// printf("false\n");
printf("The door cannot be opened.\n");
}
}
return 0;
}