poj_2513 Colored Sticks

Colored Sticks

Time Limit: 5000MS

Memory Limit: 128000K

Total Submissions: 24502

Accepted: 6431

题目链接:http://poj.org/problem?id=2513

Description

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

Input

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

Output

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

Sample Input

blue red

red violet

cyan blue

blue magenta

magenta cyan

Sample Output

Possible

Hint

Huge input,scanf is recommended.

Source

The UofA Local2000.10.14

解题思路:

这个题目主要用的是并查集+字典树+欧拉路完成的,用字典树来存放每一个单词,每个单词的最后一个字符存放每个单词对应的编号,用并查集来判断图是否连通,在用欧拉路来判断是否符合

代码:

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 510000
#define maxn 27

using namespace std;

int g[MAX];
int indegree[MAX];
int outdegree[MAX];
int set[MAX];
int num=0;
//建立字典树方便查找
struct Trie
{
    Trie *next[maxn];
	int id;
    char data;
};

//查询某个单词是否在字典树中,如果存在,返回id,不存在,返回-1
int IsExist(Trie *root,char *str)
{
    int len =strlen(str);
    int i;
    Trie *p=root;
    for(i=0;i<len;i++)
    {
        int id=str[i]-'a';
        if(p->next[id]==NULL)
            return -1;
		p=p->next[id];
		if(i==len-1)
		{
			return p->id;
		}
    }
	return -1;
}

//把字符串插入字典树root中
void build(Trie *root,char *str)
{
    Trie *p=root;
    Trie *q;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    {//把每个字符都插入到字典树中
        int id=str[i]-'a';
        if(p->next[id]!=NULL)
        {
            p=p->next[id];
            continue ;
        }
        //没有该节点
        q=(Trie *)malloc(sizeof(Trie));
        q->data=str[i];

        for(int j=0;j<maxn;j++)
        {
            q->next[j]=NULL;
        }
		if(i==len-1)
		{
			q->id=num;
		}
		else
			q->id=-1;
        p->next[id]=q;
        p=p->next[id];
    }
	num++;
}

void init()
{
	memset(g,0,sizeof(g));
    memset(indegree,0,sizeof(indegree));
    memset(outdegree,0,sizeof(outdegree));
	for(int i=0;i<MAX;i++)
	{
		set[i]=i;
	}
}

int findSet(int x)
{
	if(x!=set[x])
		set[x]=findSet(set[x]);
	return set[x];
}

void unionSet(int x,int y)
{
	int a=findSet(x);
	int b=findSet(y);
	if(a==b)
		return;
	if(set[a]<set[b])
	{
		set[b]=a;
	}
	else
	{
		set[a]=b;
	}
}

int main()
{
    int i;
	Trie *root;
    root=(Trie *)malloc(sizeof(Trie));
	for(int j=0;j<=maxn;j++)
    {
        root->next[j]=NULL;
    }

    init();
    //输入
    char ch1[12];
    char ch2[12];
    while(scanf("%s%s",ch1,ch2)!=EOF)
    {
        int s;
        int e;
		s=IsExist(root,ch1);
		if(s==-1)
		{
			build(root,ch1);
			s=num-1;
		}
		e=IsExist(root,ch2);
		if(e==-1)
		{
			build(root,ch2);
			e=num-1;
		}
        g[s]=1;
        g[e]=1;
        //点s和点e的度数自加
        indegree[e]++;
        outdegree[s]++;
        //将点s和e连接起来
        unionSet(s,e);
    }
    int count=0;
    int flag=0;

    //判断图是否连通——变量一遍所有节点,如果每一个节点的父亲都是相同的,那么图是连通的
    for(i=0;i<=num;i++)
    {
        //如果超过一个点的父亲是他本身,那么表示不连通
        if(g[i]==1 && set[i]==i)
        {
            flag++;
        }
    }

    if(flag>1)//图不连通
    {
        printf("Impossible\n");
        return 0;
    }

    //如果图连通,判读是否是欧拉路径
    /*无向图中,除源点和汇点为奇数除外,其余点的度数都为偶数,或者所有点的度数为偶数,那么存在欧拉路径*/
    for(i=0;i<=num;i++)
    {
        if(g[i]==1)
        {
            if((indegree[i]+outdegree[i])%2!=0)
            {
                count++;
            }
        }
    }
    if(count==0 || count==2)
        printf("Possible\n");
    else
        printf("Impossible\n");


    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值