思路:先分析,特殊的字母,可能有的字母是当开头个数+1=当结尾个数,那么这个字母一定是开头,同理另一个特殊字母就是作为结尾的
之后其余的字母的话只可能是开头=结尾个数,如果有任何一个字母当开头的个数和结尾个数只差为2,那么回路一定不成立!
之后是构建DFS遍历
遍历的思路就是 用G[i][j]表示字母i,j是连通的!
遍历的起点我们分为2个步骤,一个是这个图是个环路
第二个是一条线性图
环路的话从哪里都可以开始遍历
线形图的话最好从开头进行遍历
一直遍历到结尾
之后看有没有没有遍历到的节点
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define LEN 100 + 10
#define MAX_SIZE 1000 + 10
int G[LEN][LEN];
int front[LEN];
int back[LEN];
int vis[LEN];
int dfs(int u)
{
vis[u]=1;
for(int i=0;i<LEN;i++)
if(G[u][i]&&!vis[i])/*如果是连通的话*/
{
dfs(i);
}
}
int main()
{
int N;
scanf("%d",&N);
for(int cases=1;cases<=N;cases++)
{
int n,ok=1;
scanf("%d",&n);
memset(front,0,sizeof(front));
memset(back,0,sizeof(back));
memset(G,0,sizeof(G));
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
char word[MAX_SIZE];
scanf("%s",word);
int L=strlen(word);
G[word[0]-'0'][word[L-1]-'0']++;
front[word[0]-'0']++;
back[word[L-1]-'0']++;
}
int num1=0,num2=0;
for(int i=0;i<LEN;i++)
{
if(front[i]!=back[i])
{
if(front[i]==back[i]+1)
num1++;
else if(front[i]+1==back[i])
num2++;
else
{
ok=0;
break;
}
}
}
if(num1&&num2&&num1+num2>2)
ok=0;
if(ok){/*开头和结尾只能有一个*/
/*开始遍历!*/
int ok1=0;
int ok2=0;
for(int i=0;i<LEN;i++)
{
if(num1==0&&num2==0&&front[i])
{
/*如果是一个回路的图*/
dfs(i);
break;
}
else if(front[i]>back[i])
{
dfs(i);
break;
}
}
num1=0;num2=0;
for(int i=0;i<LEN;i++)
{
if(!vis[i]&&front[i]){ok=0;break;}
if(!vis[i]&&back[i]){ok=0;break;}
}
if(ok) printf("Ordering is possible.\n");
else printf("The door cannot be opened.\n");
}
else printf("The door cannot be opened.\n");
}
return 0;
}