poj 2513 Colored Sticks(trie树 + 并查集 + 欧拉图)

很好的一道题,用到了欧拉图的定义。呃,说实话,大一学的那点关于欧拉图的知识忘得都差不多了,虽然还记得欧拉图,但根本不知道怎么用,怎么判断,记得有次比赛有道题和它很像,当时根本不知道要用什么知识来解决,只是简单的假设着,今天读到这题时,直觉上觉得应该简单的方法,训练计划又提示用trie树,所以认真的推了一个结论,只有当每种颜色的数目都为偶数,或者只有两种颜色的数目为奇数其他的都为偶数时才能完成匹配,当时没想到是欧拉图,所以就按着自己的想法这样做了,可是不对,觉得应该是少了点什么,上网一查才知道这题是用欧拉图,然后又看了一下欧拉图的定义,汗~~

再来说说这道题,题目的意思是,给你一堆木棒,每个木棒的两头都涂有一种颜色,问你如果将涂有相同颜色的木棒的头对在一起,是否能将所有木棒拼成一根。

其实这题就是想问你是否有一种方案可以将每个颜色都访问一遍,也就是欧拉图的定义,在一个连通图中是否可以过每边一次且仅有一次,做起来也很简单,就是先用并查集判断一下图是否连通,然后就是用trie树判断每种颜色出现的数目了,看解题报告中提到他们也用过map集 貌似会超时,没试过,直接用的trie树。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define maxx 510006
using namespace std ;

struct node
{
    int num ;
    struct node *next[26];
}*s ;
int hash[maxx] , f[maxx] , sum ;

struct node *creat ( )//申请空间并初始化
{
    int i ;
    struct node *p ;
    p = ( struct node *) malloc ( sizeof ( struct node ));
    for ( i = 0 ; i < 26 ; i++ )
    p->next[i] = NULL ;
    p->num = 0;
    return p ;
}

void init( )//初始化
{
    s = creat ( ) ;
    memset( hash , 0 , sizeof ( hash ));
    for ( int i = 0 ; i < maxx ; i++ )
    f[i] = i ;
    sum = 0;
}

int find ( int x )//用并查集判断是否为连通图
{
    if ( x != f[x] )
    f[x] = find ( f[x] );
    return f[x] ;
}

int search ( char str[] )//用trie树标记每种颜色出现的次数
{
    int len = strlen ( str );
    int i ;
    struct node *p = s ;
    for ( i = 0 ; i < len ; i++ )
    {
        if ( p->next[str[i]-'a'] == NULL )return 0;
        p =  p->next[str[i]-'a'] ;
    }
    return p->num ;
}

int jud ( )//判断是否可能
{
    int i ;
    int ss = 0 ;
    for ( i = 1 ;  i <= sum ; i++ )//判断是否符合欧拉图特性
    if ( hash[i] % 2 )
    ss++ ;
    if ( ss != 0 && ss != 2 )
    return 0 ;
    int t = find ( 1 );
    for ( i = 2 ; i <= sum ; i++ )//判断图是否连通
    if ( t != find ( i ))
    return 0 ;
    return 1 ;
}

void insert ( char str[] , int x )//建树
{
    int len = strlen ( str );
    int i ;
    struct node *p = s , *q ;
    for ( i = 0 ; i < len ; i++ )
    {
        if ( p->next[str[i]-'a'] == NULL )
        {
           q = creat( ) ;
           p->next[str[i]-'a'] = q ;
           p = q ;
        }
        else
        p = p->next[str[i]-'a'] ;
    }
    p->num = x ;
}

int main()
{
    char str_s[15] , str_t[15] ;

    init( ) ;
    while  ( scanf ( "%s%s" , str_s , str_t ) != EOF )
    {
        int x = search ( str_s );
        int y = search ( str_t );
        if ( x == 0 ) insert ( str_s , x = ++sum );
        if ( y == 0 ) insert ( str_t , y = ++sum );
        hash[x]++ ;
        hash[y]++ ;
        int xx = find ( x );
        int yy = find ( y );
        if ( xx != yy )
        f[xx] = yy ;
    }
    if ( jud ( ) )
    printf ( "Possible\n" );
    else
    printf ( "Impossible\n" );
    return 0;
}
posted @ 2012-05-27 21:00  Misty_1  阅读(200)  评论(0编辑  收藏  举报