poj 2513 欧拉路+Trie树+并查集

传送门

题意:很多棒棒,首位有颜色,如果一个棒棒的首颜色和另一个棒棒的尾颜色相同,则可以连接在一起,问所以棒棒能否连成一线。

个人心得:通过这题学习了欧拉路,知道了用Trie把字符串映射成数字。

思路:把颜色看作节点,把棒看成边,图就建完了,之后看是否在一个连通图中,这里用并查集实现,如果在,再判断是否构成欧拉路,是就也能了。

欧拉路条件:图连通并且入度为奇数的点只有0个或2个。

Trie树映射,不会的可以学习下,据说map很慢。

吐槽:各自变量什么的都开大点,不然RE。。。。。。。。

吐槽(与本题无关):今天出去做题,被各种大牛虐的很惨,心情很不爽,励志要发愤涂墙!。。。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
struct node
{
    int c[27];
    int id;
}t[5000000];
int num,tnum,in[550005];
int f[550005];
int trie(char *a)
{
    int l=strlen(a);
    int p=0;
    for(int i=0;i<l;i++)
    {
        if(t[p].c[a[i]-'a']==0)
        {
            t[p].c[a[i]-'a']=++tnum;
            memset(t[tnum].c,0,sizeof(t[tnum].c));
            p=tnum;
            t[p].id=0;
        }
        else
        {
            p=t[p].c[a[i]-'a'];
        }
    }
    if(t[p].id==0)
    {
        t[p].id=++num;
        f[num]=num;
    }
    return t[p].id;
}
int find(int i)
{
    if(f[i]==i)return i;
    f[i]=find(f[i]);
    return f[i];
}
void un(int u,int v)
{
    int x=find(u);
    int y=find(v);
    if(x<y)f[y]=x;
    else f[x]=y;
}
int main()
{
    num=0;
    tnum=0;
    memset(in,0,sizeof(in));
    char a[30],b[30];
    memset(t[0].c,0,sizeof(t[0].c));
    while(scanf("%s%s",a,b)!=EOF)
    {
        int u=trie(a);
        int v=trie(b);
        un(u,v);
        in[u]++;
        in[v]++;
    }
    int flag=0;
    int oddnum=0;
    for(int i=1;i<=num;i++)
    {
        if(f[i]!=f[1])
        {
            flag=1;
            break;
        }
        if(in[i]%2==1)oddnum++;
    }
    if(flag)cout<<"Impossible"<<endl;
    else if(oddnum==0||oddnum==2)cout<<"Possible"<<endl;
    else cout<<"Impossible"<<endl;
    return 0;
}


你可能感兴趣的:(poj,欧拉路,Baoge)