http://poj.org/problem?id=2513

和离散数学有关  欧拉回路问题

同一颜色的标记为同一点 同一stick 的两端为相连状态

数学什么的 最不擅长了 看了别人的解析

两个限制条件

1  图为联通  可用并查集判断

2  度 (出度+入度)数为基数的点为0 或者为 2   输入时相加

不满足上述两个条件中的任何一个  都Impossible

存颜色和查询要用字典树 用map超时

代码及其注释:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<cmath>
#define LL long long

using namespace std;

const int N=550100;
int f[N];//并查集
int num[N];//度(出度+入度)
int I;//总节点数 全局变化
struct node
{
    struct node *next[26];
    int k;
}*head;
inline int findx(int x)
{
    if(f[x]!=x)
    f[x]=findx(f[x]);
    return f[x];
}
int insert(char s[])//插入颜色 并返回颜色的对应数字
{
    struct node *t,*w;
    int n=strlen(s);
    t=head;
    for(int i=0;i<n;++i)
    {
        if(t->next[s[i]-'a']==NULL)
        {
            w=new node;
            for(int j=0;j<26;++j)
            w->next[j]=NULL;
            w->k=-1;
            t->next[s[i]-'a']=w;
        }
        t=t->next[s[i]-'a'];
    }
    if(t->k==-1)
    t->k=I++;
    return t->k;
}
int main()
{
    //freopen("data.txt","r",stdin);
    for(int i=0;i<N;++i)
    {
        f[i]=i;
        num[i]=0;
    }
    head=new node;
    for(int i=0;i<26;++i)
    head->next[i]=NULL;
    head->k=-1;
    char stemp1[12],stemp2[12];
    I=0;
    int k1,k2;
    while(scanf("%s %s",stemp1,stemp2)!=EOF)
    {
        k1=insert(stemp1);
        k2=insert(stemp2);
        int l1=findx(k1);
        int l2=findx(k2);
        if(l1!=l2)//并查集 合并
        f[l1]=k2;
        ++num[k1];//增加度
        ++num[k2];
    }
    int l;
    int k=findx(0);
    int sum=0;
    for(l=0;l<I;++l)
    {
        if(findx(l)!=k)//图不联通
        {
           printf("Impossible\n");
           return 0;
        }
        if(num[l]%2)
        ++sum;
    }
    if(sum==0||sum==2)//只有基数度的点为0 和 为2 时可以
    printf("Possible\n");
    else
    printf("Impossible\n");
    return 0;
}

  

 

posted on 2012-08-11 17:57  夜->  阅读(112)  评论(0编辑  收藏  举报