用深搜超时。
后来用欧拉回路。
union set 原来是并查集 ,是种数据结构,我看英文知道有这个union set 刚开始还以为是种算法。
union set code:
int height[MAX];
int root[MAX];
for(int i=0;i<26;i++){
root[i]=i;
height[i]=1;
}
int Find(int a){
if(root[a]!=a){
root[a]=Find(root[a]);
}
return root[a];
}
void un(int a ,int b){
int x,y;
x=Find(a);
y=Find(b);
if(x!=y){
if(height[x]<height[y]){
root[y]=x;
height[x]++;
}else{
root[x]=y;
height[y]++;
}
}
}
AC 代码,用高度进行了修正,比较x,y两个根。把数量多的根,附在数量少的根上。就是说哪个根的数量比较少,哪个就是最后的根。
加上这个前是1230ms ,加上后957ms。
AC代码
#include <iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<queue>
using namespace std;
const int MAX=30;
int n;
int root[MAX];
int visited[MAX];
int in[MAX];
int out[MAX];
int p[MAX];
int height[MAX];
int Find(int a){
if(root[a]!=a){
root[a]=Find(root[a]);
}
return root[a];
}
void un(int a ,int b){
int x,y;
x=Find(a);
y=Find(b);
if(x!=y){
if(height[x]<height[y]){
root[y]=x;
height[x]++;
}else{
root[x]=y;
height[y]++;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(visited,false,sizeof(visited));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
// init root
for(int i=0;i<26;i++){
root[i]=i;
height[i]=1;
}
string tmp;
int a,b;
for(int i=0;i<n;i++){
cin>>tmp;
int len=tmp.length();
a=tmp[0]-'a';
b=tmp[len-1]-'a';
//
un(a,b);
visited[a]=true;
visited[b]=true;
out[a]++;
in[b]++;
}
//
for(int i=0;i<26;i++){
root[i]=Find(i);
}
int cnt=0;
for(int i=0;i<26;i++){
if(visited[i]&&root[i]==i)cnt++;
}
if(cnt>1){
printf("The door cannot be opened.\n");
continue;
}
int j=0;
for(int i=0;i<26;i++){
if(visited[i]&&out[i]!=in[i]){
p[j++]=i;
}
}
if(j==0){
printf("Ordering is possible.\n");
continue;
}
if(j==2&&((out[p[0]]-in[p[0]]==1&&in[p[1]]-out[p[1]]==1)||(out[p[1]]-in[p[1]]==1&&in[p[0]]-out[p[0]]==1))){
printf("Ordering is possible.\n");
continue;
}
printf("The door cannot be opened.\n");
}
return 0;
}