hdu 1116 Play on Words

用深搜超时。
后来用欧拉回路。
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值