码迷,mamicode.com
首页 > 其他好文 > 详细

[ACM] POJ 2513 Colored Sticks (Trie树,欧拉通路,并查集)

时间:2014-07-19 08:08:34      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   使用   

Colored Sticks
Time Limit: 5000MS   Memory Limit: 128000K
Total Submissions: 29736   Accepted: 7843

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


解题思路:

每根木棒两端都有一种颜色,如果两根木棒一端有相同的颜色,则可以连在一块,给出一系列木棒的颜色,问这些木棒可不可以连成一条直线。

思想为建图,一种颜色为一个节点,不同的木棒相同的颜色是一个节点,如果能连城一条直线的话,那么所建的图一定是连通图,且从起点出发,每条边只能经过一次(直线就是这样),这就想到了欧拉通路。

欧拉通路 (欧拉迹)—通过图中每条边一次且仅一次,并且过每一顶点的通路。

对于无向图来说:

G有欧拉通路的充分必要条件为:连通,G中只有两个奇度顶点(它们分别是欧拉通路的两个端点)

所以我们要解决两个问题:

1.怎样判断建的图是连通的?

2.怎样判断奇度顶点的个数?

对于第一个问题,采用并查集可以解决,只要所有的顶点都在一个集合里面,那么图一定是连通的,这又衍生出一个问题,使用并查集的时候,得需要节点的编号才可以,怎样确定节点的编号呢?可以采用trie树来确定节点的编号,cnt=1,按照颜色字符串输入的顺序,在trie树中建立一条路径,只要发现以前没有过该字符串,就让其id=cnt++,那么所输入的颜色节点的编号就变为了 1— cnt-1

对于第二个问题,用degree[]数组来保存每个顶点的度。无向图中,一个顶点的度就是有多少条边与其相连,所以在输入的时候,对于输入的两种颜色,对其编号进行degree[编号] ++就可以了。上面所说的奇度顶点(欧拉通路的两个端点),欧拉通路的两个端点有两种情况,一是颜色相同,那么在我们所建立的图上这两个端点是重合的,也就是奇度顶点的个数为0,另一种情况,颜色不同,那么奇度顶点就为2了,所以我们在这里要判断的是奇度顶点是否等于0或者等于2.

PS:做这道题真的学到好多东西。

参考:

http://blog.csdn.net/niushuai666/article/details/6549182

http://blog.csdn.net/lyy289065406/article/details/6647445

代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=250000;
int degree[maxn*2+1];//每个顶点的度
int parent[maxn*2+1];//根节点是谁
int cnt=1;//顶点的个数,一根棍子有两个顶点

struct Trie
{
    bool ok;
    int id;
    Trie *next[27];
    Trie()
    {
        ok=0;
        for(int i=0;i<=27;i++)
            next[i]=NULL;
    }
}root;

int hash(char *s)
{
    int len=strlen(s);
    Trie *p=&root;
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';
        if(!p->next[id])
            p->next[id]=new Trie;
        p=p->next[id];
    }
    if(p->ok)
        return p->id;
    else
    {
        p->ok=1;
        p->id=cnt++;
    }
    return p->id;
}

void init()
{
    for(int i=1;i<=500000;i++)
        parent[i]=i;
}

int find(int x)
{
    return parent[x]==x?x:find(parent[x]);
}

void unite(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y)
        return ;
    parent[x]=y;
}


int main()
{
    char s1[11],s2[11];
    memset(degree,0,sizeof(degree));
    init();
    while(scanf("%s%s",s1,s2)!=EOF)
    {
        int x=hash(s1);
        int y=hash(s2);
        degree[x]++,degree[y]++;
        unite(x,y);
    }
    cnt--;
    int self=0;//根节点为本身的个数
    int oddNum=0;//度为奇数的顶点的个数
    for(int i=1;i<=cnt;i++)
    {
        if(degree[i]%2)
            oddNum++;
        if(find(i)==i)
            self++;
        if(oddNum==3)//度数为奇数的定点个数>2
        {
            cout<<"Impossible"<<endl;
            return 0;
        }
        if(self==2)//不连通
        {
            cout<<"Impossible"<<endl;
            return 0;
        }
    }
    if(oddNum==0||oddNum==2)
        cout<<"Possible"<<endl;
    return 0;
}


[ACM] POJ 2513 Colored Sticks (Trie树,欧拉通路,并查集),布布扣,bubuko.com

[ACM] POJ 2513 Colored Sticks (Trie树,欧拉通路,并查集)

标签:des   style   blog   http   color   使用   

原文地址:http://blog.csdn.net/sr_19930829/article/details/37931437

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!