poj-2513 Colored Sticks

2 篇文章 0 订阅

Description

You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a straight line such that the colors of the endpoints that touch are of the same color?

Input

Input is a sequence of lines, each line contains two words, separated by spaces, giving the colors of the endpoints of one stick. A word is a sequence of lowercase letters no longer than 10 characters. There is no more than 250000 sticks.

Output

If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.

Sample Input

blue red
red violet
cyan blue
blue magenta
magenta cyan

Sample Output

Possible

    题意:木棒两段有不同的颜色,两木棒相同颜色的一端可以连接。输入每个木棒两端的颜色,问是否可以将所有木棒连接成一条线。

    思路:木棒数量即颜色数量太多,普通数组不方便存储,所以采用字典树。而颜色的两两关联性又与并查集相似,用并查集将各颜色关联。注意题意是将木棒连成一条线,所以题目要求构建欧拉图或欧拉回路,即一笔画的图,欧拉图或欧拉回路要求度为奇数的点小于两个,其他个点度为偶数。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>

using namespace std;

struct node
{
    int next[27];
    int num;
}d[510015];
int degree[510015],arr[510015];
int top,no;
int creat(char a[])
{
    int x,i;
    int len=strlen(a);
    int  j=0;
    for (i=0;i<len;i++)
    {
        x=a[i]-'a';
        if(d[j].next[x]==0)
        {
            d[j].next[x]=++top;
        }
        j=d[j].next[x];
    }
     if(d[j].num==0)
     {
         d[j].num=++no;
     }
    return d[j].num;
}
int Find(int r)
{
    return r==arr[r] ? r : arr[r]=Find(arr[r]);
}
void Union(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)
    {
        arr[fx]=fy;
    }
}
int main()
{
    memset(d,0,sizeof(d));
    memset(degree,0,sizeof(degree));
    int i;
    for (i=1;i<=510015;i++)
        arr[i]=i;
    char str1[15],str2[15];
    top=0;no=0;
    while (scanf("%s%s",str1,str2)!=EOF)
    {
        int x=creat(str1);
        int y=creat(str2);
        degree[x]++;
        degree[y]++;
        Union(x,y);
    }
    int sum=0;
    int flag=0;
    for (i=1;i<=no;i++)                                //判断奇数度个数
    {
        if(degree[i]&1)
            sum++;
        if(sum>2)
        {
            printf("Impossible\n");
            return 0;
        }
    }
    for (i=1;i<=no;i++)                               //判断根节点个数
    {
        if(arr[i]==i)
        flag++;
        if(flag>1)
        {
            printf("Impossible\n");
            return 0;
        }
    }
            printf("Possible\n");
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值