poj 2513 Colored Sticks

题目大意:

有n(n<=250000)个木棍,每个木棍两端用不同的颜色标记(以字符串形式给出),两个木棍能链接的条件是两端同颜色的两端才能接到一起,问你是否可以把所有的木棍接成一个大木棍。

题解:

一个木棍拆成两个点,构造图,那么满足条件的答案是该图是一个欧拉图,利用欧拉图的判定定理即可。对于字符串到数字的映射,可以使用tire或hash。注意此题的图不一定是联通图,所以还要用并查集判断是否联通,不联通一定不可以。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct tire
{
    int next[26];
    bool v;
    int data;
};
tire tree[255000*2]={{{0},false,0}};
char a[100],b[100];
int tot=0,len=1;
int d[1000000]={0};
int f[500000];
int insert(char * s)
{
    int l=strlen(s),now=1;
    for(int i=0;i<l;i++)
    if(tree[now].next[s[i]-'a']!=0)now=tree[now].next[s[i]-'a'];else
    {
        len++;
        tree[now].next[s[i]-'a']=len;
        now=len;
    }
    if(tree[now].v==true) d[tree[now].data]++;
    else
    {
        tot++;
        tree[now].data=tot;
        tree[now].v=true;
        d[tot]=1;
    }
    return tree[now].data;
}
int find(int x)
{
    return f[x]<0?x:f[x]=find(f[x]);
}
int main()
{
    int ans=0;
    for(int i=0;i<=500000;i++)
    f[i]=-1;
    while(scanf("%s %s",a,b)!=EOF)
    {
        int x=insert(a),y=insert(b);
        int fx=find(x),fy=find(y);
        if(fx!=fy)//启发式合并
        {
            if(f[fx]>f[fy])
            {
                f[fy]+=f[fx];
                f[fx]=fy;
            }
            else
            {
                f[fx]+=f[fy];
                f[fy]=fx;
            }
        }
    }
    bool flag=true;int fa=find(tot);
    for(int i=1;i<=tot;i++)
    {
    if(d[i]%2==1)ans++;
    if(find(i)!=fa){flag=false;break;}
    }
    if(flag&&(ans==2||ans==0))printf("Possible\n");else printf("Impossible\n");
    return 0;
}


你可能感兴趣的:(poj 2513 Colored Sticks)