POJ - 2513 Colored Sticks 欧拉回路(一笔画)+trie

本文介绍了一种使用欧拉回路和Trie树解决复杂木棍连接问题的方法。问题中,需将带有颜色标记的木棍首尾相连形成完整链条,确保相连两端颜色相同。通过构建Trie树存储颜色信息,利用欧拉回路判断是否能成功连接所有木棍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

题意:有n个木棍,木棍两端分别有颜色,要求把木棍两两首尾相连,保证首尾相连的两端颜色一致,问是否能够把这n根木棍连成一整根木棍。

思路:最开始想的是把每根木棍都当成点跑最长路看是否达到n-1的长度,但是这题有环而且数据范围太大。。。但是如果我们把木棍当成边,每种颜色当成点,那么是否能连成一整根木棍就相当于是否能一笔画的问题,即求解欧拉回路,由于这题n过大,用map的话有可能会超时,所以用trie来存颜色及其对应的点即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define PI acos(-1)
#define INF 0x3f3f3f3f
#define NUM 250100
#define debug false
#define ll long long
#define lowbit(x) ((-x)&x)
#define ffor(i,d,u) for(int i=d;i<=u;++i)
#define _ffor(i,u,d) for(int i=u;i>=d;--i)
#define mst(array,Num) memset(array,Num,sizeof(array))
const int p = 1e9+7;
char a[11];
int fa[NUM<<1];
int color[NUM<<1]={};
int cnt=0,num=0,sticknum=0;
struct Trie
{
    int id;
    int po[26];
    void clean()
    {
        mst(po,0);
        id=0;
    }
}t[NUM<<3];
template <typename T>
void read(T& x)
{
    x=0;
    char c;T t=1;
    while(((c=getchar())<'0'||c>'9')&&c!='-');
    if(c=='-'){t=-1;c=getchar();}
    do((x*=10)+=((int)(c-'0')));while((c=getchar())>='0'&&c<='9');
    x*=t;
}
template <typename T>
void write(T x)
{
    int len=0;char c[21];
    if(x<0)putchar('-');
    x=abs(x);
    do{++len;c[len]=(char)((x%10)+'0');}while(x/=10);
    _ffor(i,len,1)putchar(c[i]);
}
int ffa(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x]=ffa(fa[x]);
}
int in()
{
    int j=0,i=0,l=strlen(a),k;
    while(i<l)
    {
        k=a[i]-'a';
        if(t[j].po[k]==0)
        {
            ++num;
            t[num].clean();
            t[j].po[k]=num;
        }
        j=t[j].po[k];
        ++i;
    }
    if(t[j].id==0)
    {
        t[j].id=++cnt;
        fa[cnt]=cnt;
    }
    return t[j].id;//该颜色对应的点编号
}
inline void init()
{
    int l,fa1,fa2,v1,v2;
    t[0].clean();
    while(scanf("%s",&a)!=EOF)
    {
        ++sticknum;
        v1=in();
        scanf("%s",&a);
        v2=in();
        fa1=ffa(v1);fa2=ffa(v2);
        if(v1!=v2)++color[v1],++color[v2];
        if(fa1!=fa2)
            fa[fa1]=fa2;
    }
}
bool check()
{
    int ans;
    if(sticknum==1||sticknum==0)
        return true;
    ans=ffa(1);
    ffor(i,2,cnt)
        if(ffa(i)!=ans)//判断图的连通性
            return false;
    ans=0;
    ffor(i,1,cnt)
        if(color[i]&1)++ans;
    if(ans>2||ans==1)return false;
    return true;
}
void AC()
{
    init();
    if(!check())
        puts("Impossible");
    else
        puts("Possible");
}
int main()
{
    AC();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值