POJ 2513 Colored Sticks

给你250000个棒子,棒子两头有颜色,问你可不可以用完所有的棒子,把棒子连起来,并且使得棒子相连的两头颜色一样。

其实就是求欧拉回路。

无向图存在欧拉路的充要条件为:

   1->图是连通的;

   2->所有节点的度为偶数,或者有且只有两个度为奇数的节点。

判断图的连通性,用并查集搞定。又题目给的棒子颜色是字符串,所以要用trie树把每个颜色的编号记录下来。

注意,这里用map会超时。。因为map基于hash,并不高效,所以这里需要用trie树来处理。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define MAX 260000
int uset[MAX],degree[26000];
int BCG_root(int k)
{
    if(k==uset[k])return k;
        return uset[k]=BCG_root(uset[k]);
}
int BCG_init()
{
    for(int i=0;i<MAX;++i)
        uset[i]=i;
    return 0;
}
struct node
{
    int flag; //如果是终止状态,则标记是哪个字符
    int tag;
    int next[26];
    int init()
    {
        memset(next,-1,sizeof(next));
        flag=0;
        tag=0;
        return 0;
    }
}trie[260000];
int size=1;
const int root=0;
int val(char a)
{
    return a-'a';
}
int insert(char* s,int k)
{
    int p=root;
    for(int i=0;s[i];++i)
    {
        int v=val(s[i]);
        if(trie[p].next[v]==-1)
        {
            trie[p].next[v]=size;
            trie[size].init();
            ++size;
        }
        p=trie[p].next[v];
    }
    trie[p].tag=1;
    trie[p].flag=k;
    return 0;
}
int match(char* s)
{
    int p=root;
    for(int i=0;s[i];++i)
    {
        int v=val(s[i]);
        p=trie[p].next[v];
        if(trie[p].tag)
        return trie[p].flag;
    }
    return 0;
}
void init()
{
    size=1;
    trie[root].init();
    return ;
}
int main()
{
    char str[15];
    int n,cnt,i,j,anc,sum,t1,t2;
    init();
    BCG_init();
    cnt=1;
    memset(degree,0,sizeof(degree));
    while (scanf("%s",str) != EOF)
   // for (int k=0; k<5; k++)
    {
      //  scanf("%s",str);
        j=match(str);
        if (j == 0)
        {
            insert(str,cnt);
            degree[cnt]++;
            t1=cnt;
            cnt++;
        }
        else
        {
            degree[j]++;
            t1=j;
        }
        scanf("%s",str);
        j=match(str);
        if (j == 0)
        {
            insert(str,cnt);
            degree[cnt]++;
            t2=cnt;
            cnt++;
        }
        else
        {
            degree[j]++;
            t2=j;
        }
        uset[BCG_root(t1)]=BCG_root(t2);
    }
    anc=BCG_root(1);
    sum=0;
  //  printf("anc=%d\n",anc);
    for (i=1; i<cnt; i++)
    {
       // printf("%d\n",i);
       // printf("%d\n",BCG_root(i));
       // printf("!!\n");
        if (BCG_root(i) != anc)
        {
          //  printf("@");
          break;
        }
        if (degree[i]%2 == 1)
            sum++;
    }
    if (i != cnt || (sum != 2 && sum != 0))
        printf("Impossible\n");
    else
        printf("Possible\n");
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值