不得不说,这道题是自己做得比较开心的一道题,总共写了两份代码,一份是看题解前自己的做法,一份是看了题解的做法,自己的想法是把每个单词当成一个点,让后直接dfs,一个节点两头搜,就是顺向和逆向搜,顺向搜到尽头后,逆向搜,如果在不访问已经访问过的点的时候能够搜到的点数补上前面的点数,刚好是所有点的个数,就成功了,不过时间较长,不过没有time limit exceeded,还ac了,不过也用了1s,很开心。第二份是看别人的思路的,不过只看思路,没看别人的代码,代码自己写,最核心的就是把每个单词当成一条线段,头尾字母成节点,这样就只需26个字母,重复的就是交叉点,很强大。然后我用BFS看连通性,在用欧拉道路的特点看每个节点的出入度,出结果,快了100倍,0,02s就解决了。
第一份
#include<stdio.h>
#include<string.h>
//虽然时间有点长,但是是自己写的,很开心,整个算法都是自己想的
typedef struct node{
int index,chn;
node(int i,int c){index=i;chn=c;}
}node;
int pre[30][100500],post[30][100500],vis[100500],pre_num[30],post_num[30],words[100600][2],count,n;
char word[1050];
int dfs_pre_post(int count){
node *stk2[100000];
int top=0,child;
stk2[top]=new node(0,0);
while(top!=-1){
if(stk2[top]->chn<post_num[words[stk2[top]->index][0]]){
child=post[words[stk2[top]->index][0]][stk2[top]->chn];
stk2[top]->chn++;
if(!vis[child]){
stk2[++top]=new node(child,0);
vis[child]=1;
count++;
}
}
else{
if(count==n) return 1;
else{
while(top!=-1&&stk2[top]->chn==post_num[words[stk2[top]->index][0]]){
vis[stk2[top]->index]=0;
count--;
top--;
}
}
}
}
vis[0]=1;
return 0;
}
void dfs_post_pre(){
node *stk[100000];
int top=0,child;
count++;
stk[0]=new node(0,0);
vis[0]=1;
while(top!=-1){
if(stk[top]->chn<pre_num[words[stk[top]->index][1]]){
child=pre[words[stk[top]->index][1]][stk[top]->chn];
stk[top]->chn++;//此处改变,下面就不能在用,我是看当前的孩子,上一行保存
if(!vis[child]){
stk[++top]=new node(child,0);//不要急着改变top,下面会用到,上面也会用到
vis[child]=1;
count++;
}
}
else{
if(count==n||dfs_pre_post(count)){
printf("Ordering is possible.\n");
break;
}
else{
while(top!=-1&&stk[top]->chn==pre_num[words[stk[top]->index][1]]){
vis[stk[top]->index]=0;
count--;
top--;
}
}
}
}
if(top==-1){
printf("The door cannot be opened.\n");
}
}
main()
{
int T,i,l;
scanf("%d",&T);
while(T--){
memset(pre_num,0,sizeof(pre_num));
memset(post_num,0,sizeof(post_num));
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",word);
pre[word[0]-97][pre_num[word[0]-97]++]=i;
l=strlen(word);
post[word[l-1]-97][post_num[word[l-1]-97]++]=i;
words[i][0]=word[0]-97;
words[i][1]=word[l-1]-97;
}
count=0;
dfs_post_pre();
memset(vis,0,sizeof(vis)/100500*n);
}
}
第二份
#include<stdio.h>
#include<string.h>
#define mod 100000
int G[30][30],degree[30][2],vtx[30],que[100000];
char word[1050];
int BFS(int max,int vn){
int head=0,tail=1,i,vis[30],count=0;
memset(vis,0,sizeof(vis));
que[0]=vtx[0];
vis[vtx[0]]=1;
count++;
while(head!=tail){
for(i=0;i<=max;i++)
if(G[que[head]][i]&&!vis[i]){
que[tail]=i;
vis[i]=1;
count++;
tail=(tail+1)%mod;
}
if(count==vn) return 1;
head=(head+1)%mod;
}
return 0;
}
main(){
int T,n,i,l,v,max,a,b,t;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
t=0;
memset(G,0,sizeof(G));
for(i=v=max=0;i<n;i++){
scanf("%s",word);
l=strlen(word)-1;
if(!degree[word[0]-97][0]&&!degree[word[0]-97][1]){
vtx[v++]=word[0]-97;
max=max>word[0]-97?max:word[0]-97;
}
degree[word[0]-97][0]++;
if(!degree[word[l]-97][0]&&!degree[word[l]-97][1]){
vtx[v++]=word[l]-97;
max=max>word[l]-97?max:word[l]-97;
}
degree[word[l]-97][1]++;
G[word[0]-97][word[l]-97]=1;
G[word[l]-97][word[0]-97]=1;
}
if(BFS(max,v)){
for(i=l=a=b=0;i<v;i++)
{
if(degree[vtx[i]][0]==degree[vtx[i]][1])l++;
else if(degree[vtx[i]][0]-degree[vtx[i]][1]==1)a=1;
else if(degree[vtx[i]][1]-degree[vtx[i]][0]==1)b=1;
degree[vtx[i]][0]=degree[vtx[i]][1]=0;
}
if((l==v-2&&a==1&&b==1)||l==v)
{
printf("Ordering is possible.\n");
t=1;
}
}
else memset(degree,0,sizeof(degree));
if(!t)printf("The door cannot be opened.\n");
}
}