POJ2513 Colored Sticks(欧拉)

题目链接

题目大意:

给很多木棍,两端被涂了颜色。任意两根木棍的相同颜色处可以拼接在一起,问有没有可能将所有的木棍都连起来,成一条直线?

 

分析:

考点,欧拉道路。

将一根木棍看成一条边,两端的颜色看成两个点,问题成了,能否从无向图的一个结点出发走出一条道路,每条边恰好经过一次。

 

求法:

如果一个无向图连通的,且最多有两个奇点(奇点指的是度数是奇数的点),则一定存在欧拉道路。

是否连通可以通过并查集来求。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
using namespace std;

const int maxn = 500000+10+10;

int deg[maxn], cm, cn, p[maxn];

struct node {
    struct node *next[26];
    int num;
}mem[250000*40+10];

node *create() {
    for(int i=0; i<26; i++) {
        mem[cm].next[i] = NULL;
    }
    mem[cm].num = 0;
    return &mem[cm++];
}

int get_num(node *&root, char s[]) {
    int len = strlen(s);
    node *p;

    if(!root) root = create();

    p = root;
    for(int i=0; i<len; i++) {
        int k = s[i] - 'a';
        if(!p->next[k]) p->next[k] = create();
        p = p->next[k];
    }

    if(!p->num) p->num = cn++;
    return p->num;
}

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

void Union(int x, int y) {
    x = find(x), y = find(y);
    if(x != y) p[x] = y;
}

int main(){
    int u, v;
    char s1[20], s2[20];
    node *root = NULL;

    cm = 0, cn = 1;

    memset(deg, 0, sizeof(deg));

    for(int i=1; i<maxn; i++) p[i] = i;

    while(scanf("%s %s", s1, s2) == 2) {
        u = get_num(root, s1);
        v = get_num(root, s2);

        deg[u]++;
        deg[v]++;

        Union(u, v);
    }

    int pn= 0;
    bool flag = true;

    int e = find(1);

    for(int i=1; i<cn; i++) {  //从1开始编号
        if(deg[i] % 2 != 0) {
            pn++;
        }

        if(pn > 2 || find(i) != e) {
            flag = false; break;
        }
    }

    if(flag) printf("Possible\n");
    else printf("Impossible\n");

    return 0;
}

 

posted on 2013-08-06 09:53  Still_Raining  阅读(237)  评论(0编辑  收藏  举报