poj2513 Colored Sticks(tire树+路径压缩并查集+欧拉通路)

偶尔看到的这个题目。。实在是太屌了。。一道题包含三个内容。。

首先题意是 给出一堆木棍 每个木棍两段各有一种颜色。然后把这些木棍连成长木棍。然后 连接处必须颜色相等。

因为不是练成圈 所有是欧拉通路就行。

这个题目考查三个地方。第一个是欧拉通路  一个条件是 所有点的度数要么全是偶数 要么有两个是奇数

第二个地方是并查集 因为欧拉通路的 另一个条件是 这个图当然得是联通的。。判连通性直接并查集就行。因为这个只要判断联通性 所以可以路径压缩了。


第二点就是带路径压缩的并查集了 前几天刚敲过。。


第三个就是tire数 就是字典树。以前好像写过一次字典树 先写一个博文把那个回顾一下吧。是hdu1251

困了。。明儿再写吧。。


wa了一次ac了 wa是因为忘记把输出中间结果的那句printf注释掉了。。


我觉得这个题目的新亮点就是 那个findindex函数  用一个字符串做参数 然后在字典树里面找 如果找不到 就一直new Node(); 最后 这个Node的index=color++;

如果找到了直接就返回index 就是要找到这种颜色代表的节点的编号。

之后就简单点了  路径压缩的并查集查找 合并。

然后看fa数组 是不是有多于一个的-1  如果有 就说明这个图不连通 那么不满足欧拉通路的第一个条件

再看第二个条件 其实两个条件同时判断的 因为遍历一遍就行

degree数组取bool就行 每次取非 偶数次还是0 奇数次就是一了

1的个数大于二 就不行

最后看1的个数是不是1

一开始并查集没用路径压缩 1800+ms 加了路径压缩 1300+ms

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn=250000*2+100;

struct Node
{
    int index;
    Node * child[26];
    Node()
    {
        index=-1;
        for(int i=0; i<26; ++i)
            child[i]=NULL;
    }
};
Node *root,*p;
int color;
bool degree[maxn];
int fa[maxn];

int findindex(char str[])
{
    p=root;
    int i,j,len=strlen(str);
    for(i=0; i<len; ++i)
    {
        if(p->child[str[i]-'a']==NULL)
        {
            p->child[str[i]-'a']=new Node();
        }
        if(i==len-1)
        {
            if(p->child[str[i]-'a']->index==-1)
            {
                p->child[str[i]-'a']->index=color;
                return color++;
            }
            else
                return p->child[str[i]-'a']->index;
        }
        p=p->child[str[i]-'a'];
    }
}

int findset(int x)
{
    return (fa[x]==-1)? x : fa[x]=findset(fa[x]);
}

void Union(int x,int y)
{
    int x1=findset(x);
    int x2=findset(y);
    if(x1!=x2)
        fa[x1]=x2;
}


int main()
{
    root =new Node();
    color=0;
    memset(degree,0,sizeof(degree));
    memset(fa,-1,sizeof(fa));
    char str1[15],str2[15];
    while(scanf("%s %s",str1,str2)!=EOF)
    {
        int x1=findindex(str1);
        int x2=findindex(str2);
        degree[x1]=!degree[x1];
        degree[x2]=!degree[x2];
        Union(x1,x2);
    }
    int cnt=0,cnt2=0;
    for(int i=0; i<color; ++i)
    {
        if(fa[i] == -1) cnt2++;
        if(degree[i])
            cnt++;
        if(cnt>2 || cnt2>1)
        {
            printf("Impossible\n");
            return 0;
        }
    }
    if(cnt==1)
    {
        printf("Impossible\n");
        return 0;
    }
    printf("Possible\n");
    return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值