Colored Sticks POJ - 2513 并查集,字典树,欧拉回路

27 篇文章 0 订阅

这道题涉及的知识点比较多

前面的博客是为这道题打基础

步入正题,题意是说给出一堆木棒,每根木棒的左边和右边颜色不一样,求能否将所有的木棒按规则连成一条直线,规则是相连的木棒端点处颜色必须一致。

如果可以输出Possible

例如题目中给出的例子(后面的序号是我自己加的)

blue red                         1
red violet                       2
cyan blue                        3
blue magenta                     4
magenta cyan                     5

可以按照  4 5 3 1 2的顺序连接起来。

解题思路就是利用并查集,字典树,以及欧拉回路的知识点,

如果不知道并查集可以参照本博客的并查集那篇博客,然后做畅通工程 HDU - 1232这道题练习一下,本博客上也有解题思路,然后了解一下字典树,可以参考一下http://blog.csdn.net/jiutianhe/article/details/8076835这篇文章,讲的很清楚了,欧拉回路简单了解一下,可以参考这篇博客相关内容的讲解。http://blog.csdn.net/lyy289065406/article/details/6647445。

然后贴上我的代码

#include<cstdio>
#include<iostream>
#include<cstring>
#define N 2500005*2
using namespace std;
int pre[N];
int indgr[N];
int trie[N][26];
int nodeNum, pr, cnt, oddDgr, root;
int find(int x)
{
    int r=x;
    while(r!=pre[r])//若r的前导点不是它本身
    {
        r=pre[r];//查找
    }

    //路径压缩
    int i=x,j;
    while(i!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;//返回查找到的根节点
}
//合并
void join(int x,int y)
{
    int rx=find(x),ry=find(y);
    if(rx!=ry)
    {
        pre[rx]=ry;
    }
}
int main()
{
    char color[15];
    int i;
    for(i=0; i<N; ++i)
        pre[i]=i;
    while(~scanf("%s",color))
    {
        cnt++;
        int cur=0,L=strlen(color);
        for(i=0; i<L; ++i)
        {
            int k=color[i]-'a';
            if(!trie[cur][k])
                trie[cur][k]=++nodeNum;
            cur=trie[cur][k];
        }

        ++indgr[cur];
        if(cnt%2)pr=cur;
        else
            join(pr,cur);
    }
    for( i=0; i<=nodeNum; ++i)
    {
        if(indgr[i]%2)++oddDgr;
        if(indgr[i]&&pre[i]==i) ++root;
        if(oddDgr>2||root>1) break;
    }
    if(((oddDgr==0 || oddDgr==2) && root==1) || (oddDgr==0 && root==0))
        printf("Possible\n");
    else
        printf("Impossible\n");
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值