poj 2513 Colored Sticks (字典树+欧拉回路判定)

Colored Sticks
Time Limit: 5000MS   Memory Limit: 128000K
Total Submissions: 27792   Accepted: 7346

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

Hint

Huge input,scanf is recommended.

Source

The UofA Local 2000.10.14


感想:

以为这题很水,开始写的两个代码果断TLE,后来才发现要用字典树的知识,然后又是WA,原来还要考虑输入为空的时候的情况要输出“Possible”,汗。。。!这数据,真蛋疼。还有要注意的是这题应该看做无向图。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <map>
#define maxn 500005
#define MAX 26
using namespace std;

int n,m,ans,t,num;
int sset[maxn],srank[maxn];
int in[maxn];
char s1[105],s2[105];
struct Trie                   //Trie结点声明
{
    int isStr;               //标记该结点处是否构成单词
    Trie *next[MAX];          //儿子分支
};

void insert(Trie *root,const char*s)    //将单词s插入到字典树中
{
    if(root==NULL||*s=='\0') return;
    int i;
    Trie *p=root;
    while(*s!='\0')
    {
        if(p->next[*s-'a']==NULL)       //如果不存在,则建立结点
        {
            Trie *temp=(Trie *)malloc(sizeof(Trie));
            for(i=0; i<MAX; i++)
            {
                temp->next[i]=NULL;
            }
            temp->isStr=0;
            p->next[*s-'a']=temp;
            p=p->next[*s-'a'];
        }
        else
        {
            p=p->next[*s-'a'];
        }
        s++;
    }
    p->isStr=++t;                  //单词结束的地方标记此处可以构成一个单词
}
int search(Trie *root,const char*s) //查找某个单词是否已经存在
{
    Trie *p=root;
    while(p!=NULL&&*s!='\0')
    {
        p=p->next[*s-'a'];
        s++;
    }
    if(p!=NULL&&p->isStr!=0) return p->isStr;  //在单词结束处的标记为true时,单词才存在
    return 0;
}
void del(Trie *root)                     //释放整个字典树占的堆区空间
{
    int i;
    for(i=0; i<MAX; i++)
    {
        if(root->next[i]!=NULL)
        {
            del(root->next[i]);
        }
    }
    free(root);
}
void init()
{
    int i;
    for(i=0; i<maxn; i++)
    {
        sset[i]=i;
        srank[i]=1;
    }
    num=0;
}
int sfind(int x)        // 查找时优化了路径
{
    int r=x,nn;
    while(sset[r]!=r) r=sset[r];
    while(x!=r)
    {
        nn=sset[x];
        sset[x]=r;
        x=nn;
    }
    return r;
}
void smerge(int a,int b)    // 合并时将深度小的集合合并到大的里面
{
    int x,y;
    x=sfind(a);
    y=sfind(b);
    if(x!=y)
    {
        if(srank[x]<srank[y])  sset[x]=y;
        else
        {
            sset[y]=x;
            if(srank[x]==srank[y])  srank[x]++;
        }
        num++;
    }
}
bool solve()
{
    int i,j,u,h;
    u=0;
    if(num!=t-1) return false ;
    for(i=1;i<=t;i++)
    {
        if(in[i]&1) u++;
    }
    if(u==0||u==2) return true ;
    return false ;
}
int main()
{
    int i,j,x,y;
    t=0;
    init();
    Trie *root= (Trie *)malloc(sizeof(Trie));
    for(i=0; i<MAX; i++)
    {
        root->next[i]=NULL;
    }
    root->isStr=0;
    memset(in,0,sizeof(in));
    while(~scanf("%s%s",s1,s2))
    {
        x=search(root,s1);
        if(!x)  // 不存在就建立
        {
            insert(root,s1);
            x=t;
        }
        y=search(root,s2);
        if(!y)
        {
            insert(root,s2);
            y=t;
        }
        in[x]++;
        in[y]++;
        smerge(x,y);
    }
    if(t==0)
    {
        printf("Possible\n");
        return 0;
    }
    if(solve()) printf("Possible\n");
    else printf("Impossible\n");
//    del(root);
    return 0;
}




你可能感兴趣的:(poj 2513 Colored Sticks (字典树+欧拉回路判定))