POJ 2513 Colored Sticks

 算法:trie树&并查集 

难度:NOIP++ 思路不简单

    说实话,这道题真的很难想到用trie树,反正不看题解我是想不到...
    首先介绍一下 欧拉(通)路,额,主要是它的性质
    **欧拉通路**
    1、定义:通过图中每条边且只通过一次,并且经过每一顶点的通路。
    2、判定方法
        (1)无向图是否具有欧拉通路的判定: 图连通;图中只有0个或2个度为奇数的节点
        (2)有向图是否具有欧拉通路的判定:图连通;除2个端点外其余节点入度=出度;1个端点入度比出度大1;一个端点入度比出度小1 或 所有节点入度等于出度。
    **欧拉回路**
    1、定义:通过图中每条边且只通过一次,并且经过每一顶点的回路。
    2、判定方法
       (1)无向图是否具有欧拉回路的判定:
       (2)有向图是否具有欧拉回路的判定:图连通;所有节点入度等于出度。
    好了,然后我们回来,发现它是欧拉通路!
    考虑它的判定,然后就发现,我们想用并查集,联系起关系,
    可是,字符串怎么玩并查集?   (有可能可以吧)tao...
    所以我们再一次用到trie树,插入时记录它们的编号,再去跑并查集,就好了。。。

为什么N只有>=500015才能过?????????

连续三次因为数组开的有问题而RE,MLE,WA,学弟带我学语法。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <algorithm>
#define ll long long
#define N 500015
using namespace std;
char a[N],b[N];
int trie[N][30];
int vis[N],fa[N];
int cnt=1,v;
int insert(char *m)
{
    int now = 0,len = strlen(m);
    for (int i = 0;i < len;i++)
    {
        int temp=m[i]-'a';
        if (!trie[now][temp])
        {
            vis[cnt]=0;
            trie[now][temp]=cnt++;
        }
        now=trie[now][temp];
    }
    if (!vis[now])   vis[now] = ++v;
    return vis[now];
}
int findf(int x)
{
    if(x==fa[x]) return x;
    return findf(fa[x]);
}
int degr[N];
void merg(int x,int y)
{
    int u1=findf(x);
    int u2=findf(y);
    if(u1!=u2) fa[u1]=u2;
}
int main()
{
    for(int i = 1;i <= N-3;i++)
    {
        fa[i]=i;
    }
    while(scanf("%s%s",a,b)!=EOF)
    {
        int t1=insert(a);
        int t2=insert(b);
        degr[t1]++;
        degr[t2]++;
        merg(t1,t2);
    }
    int ans=0;
    for (int i = 1;i <= v;i++)
    {
        if (degr[i]%2==1) ans++;
        if (ans>2||findf(1)!=findf(i))
        {
            puts("Impossible");
            return 0;
        }
    }
    if(ans==1) puts("Impossible");
    else puts("Possible");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值