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

来源:互联网 发布:软件测试作业 编辑:程序博客网 时间:2024/05/22 15:38

传送门

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

个人心得:通过这题学习了欧拉路,知道了用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;}