uva 10129 - Play on Words

不得不说,这道题是自己做得比较开心的一道题,总共写了两份代码,一份是看题解前自己的做法,一份是看了题解的做法,自己的想法是把每个单词当成一个点,让后直接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");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值