POJ_2513_Colored Sticks(欧拉路+字典树)

来源:互联网 发布:网络通信公司简介 编辑:程序博客网 时间:2024/05/20 09:08

Colored Sticks

Time Limit: 5000MS Memory Limit: 128000KTotal Submissions: 31721 Accepted: 8391

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 redred violetcyan blueblue magentamagenta cyan

Sample Output

Possible


题意:给你一些个木棒,每根木棒两端都着了 色,问能否将它们排成一条线,使得接触点的颜色是一样的。

解析:很明显的求欧拉路问题。一开始用map转化超时,后来去学了用字典树的方法处理。值得注意的是,trie数组得开足够大,我是开550000。反正在这个数组上面RE了n次心都碎了。

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

代码清单:

#include<map>#include<cmath>#include<stack>#include<queue>#include<ctime>#include<cctype>#include<string>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;struct edge{    int point;    int letter[30];}trie[550000];int number=0,Point=0;int father[550000];char s1[15],s2[15];int degree[550000];int Find(int x){    if(x!=father[x]) return Find(father[x]);    return father[x];}int GetPoint(char s[]){    int j=0;    int len=strlen(s);    for(int i=0;i<len;i++){        if(trie[j].letter[s[i]-'a'])            j=trie[j].letter[s[i]-'a'];        else{            trie[j].letter[s[i]-'a']=++number;            j=number;        }    }    if(trie[j].point==0) trie[j].point=++Point;    return trie[j].point;}bool IsEuler(int n){    int cnt=0,temp=0;    for(int i=1;i<=n;i++){        if(father[i]==i) cnt++;        if(degree[i]%2)  temp++;    }    if(cnt>1) return false;    else{        if(temp==0||temp==2) return true;        else return false;    }}int main(){    memset(trie,0,sizeof(trie));    memset(degree,0,sizeof(degree));    for(int i=0;i<550000;i++) father[i]=i;    //freopen("liuchu.txt","r",stdin);    while(scanf("%s%s",s1,s2)!=EOF){        int point1=GetPoint(s1);        int point2=GetPoint(s2);        degree[point1]++;        degree[point2]++;        point1=Find(point1);        point2=Find(point2);        father[point1]=point2;    }    if(IsEuler(Point)) printf("Possible\n");    else printf("Impossible\n");    return 0;


字典树部分可以用指针来写,用数组的弊端就是容易RE。

代码清单:

#include<map>#include<cmath>#include<stack>#include<queue>#include<ctime>#include<cctype>#include<string>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int MAX = 26;struct trie{    int point;    trie *next[MAX];};trie *root=new trie;int father[550000];char s1[15],s2[15];int degree[550000],Point=0;int Find(int x){    if(x!=father[x]) return Find(father[x]);    return father[x];}int GetPoint(char s[]){    trie *p=root, *q;    int len=strlen(s), pos;    for(int i=0;i<len;i++){        pos=s[i]-'a';        if(p->next[pos]==NULL){            q=new trie;            q->point=0;            for(int j=0;j<MAX;j++)                q->next[j]=NULL;            p->next[pos]=q;            p=p->next[pos];        }        else{            p=p->next[pos];        }    }    if(p->point==0) p->point=++Point;    return p->point;}bool IsEuler(int n){    int cnt=0,temp=0;    for(int i=1;i<=n;i++){        if(father[i]==i) cnt++;        if(degree[i]%2)  temp++;    }    if(cnt>1) return false;    else{        if(temp==0||temp==2) return true;        else return false;    }}int main(){    memset(degree,0,sizeof(degree));    for(int i=0;i<MAX;i++) root->next[i]=NULL;    for(int i=0;i<550000;i++) father[i]=i;   // freopen("liuchu.txt","r",stdin);    while(scanf("%s%s",s1,s2)!=EOF){        int point1=GetPoint(s1);        int point2=GetPoint(s2);        degree[point1]++;        degree[point2]++;        point1=Find(point1);        point2=Find(point2);        father[point1]=point2;    }    if(IsEuler(Point)) printf("Possible\n");    else printf("Impossible\n");    return 0;}


0 0