poj_2513 Colored Sticks

来源:互联网 发布:linux开启smb服务 编辑:程序博客网 时间:2024/06/06 12:35

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 27using 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,不存在,返回-1int 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;}elseq->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;}