poj 2513 Colored Sticks,无向欧拉图的判定,Trie,hash

题意:
给定一些木棒,木棒两端都涂上颜色,求是否能将所有木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。



无向欧拉图:不存在或只存在两个奇度顶点

并查集判断图的连通性 //判断是否只有一个根结点
Trie或者hash给每种颜色编号


静态数组Trie

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;

const int maxn = 520000;
int du[maxn], f[maxn];
int n;
int findset(int x) {
    return x==f[x]?x:f[x]=findset(f[x]);
}

//Trie
int ch[maxn][26];
int id[maxn];
int sz;

int Insert(char s[]) {
    int u = 0, len = strlen(s);
    for(int i=0; i<len; ++i) {
        int c = s[i] - 'a';
        if(!ch[u][c]) {
            memset(ch[sz], 0, sizeof ch[sz] );
            id[sz] = 0;
            ch[u][c] = sz++;
        }
        u = ch[u][c];
    }
    if(!id[u]) id[u] = ++n;
    return id[u];
}

void init() {
    for(int i=0; i<maxn; ++i) {
        f[i] = i;
        du[i] = 0;
    }
    sz = 1;
    n = 0;
    memset(ch[0], 0, sizeof ch[0] );
}

int main() {
    char str1[20], str2[20];

    init();

    while(~scanf("%s %s", str1, str2)) {
        int a = Insert(str1); //同时返回编号
        int b = Insert(str2);
        du[a]++;
        du[b]++;
        int pa = findset(a);
        int pb = findset(b);
        if(pa != pb) {
            f[pa] = pb;
        }
    }

    int cnt_root = 0;
    for(int i=1; i<=n; ++i){
        if(f[i]==i){
            if(++cnt_root>1){
                puts("Impossible");
                return 0;
            }
        }
    }

    int oddn = 0;
    for(int i=1; i<=n; ++i) {
        if(du[i]&1) oddn++;
    }

    if(oddn==0 || oddn==2) {
        puts("Possible");
    } else {
        puts("Impossible");
    }
    return 0;
}



静态链式Trie

//Trie
int head[maxn];
int next[maxn];
char ch[maxn];
int id[maxn];
int sz;

int Insert(char s[]) {
    int u = 0, v, len = strlen(s);
    for(int i=0; i<len; ++i) {
        bool flag = false;
        for(v = head[u]; v!=0; v=next[v])
            if(ch[v]==s[i]) {
                flag = true;
                break;
            }
        if(!flag) {
            v = sz++;
            ch[v] = s[i];
            next[v] = head[u];
            head[u] = v;
            head[v] = 0;
        }
        u = v;
    }

    if(!id[u]) id[u] = ++n;
    return id[u];
}

void init() {
    for(int i=0; i<maxn; ++i) {
        f[i] = i;
        du[i] = 0;
    }
    sz = 1;
    head[0] = next[0] = 0;
    n = 0;
}

int main() {
    char str1[20], str2[20];

    init();

    while(~scanf("%s %s", str1, str2)) {
        int a = Insert(str1); //同时返回编号
        int b = Insert(str2);
        du[a]++;
        du[b]++;
        int pa = findset(a);
        int pb = findset(b);
        if(pa != pb) {
            f[pa] = pb;
        }
    }

    int cnt_root = 0;
    for(int i=1; i<=n; ++i){
        if(f[i]==i){
            if(++cnt_root>1){
                puts("Impossible");
                return 0;
            }
        }
    }

    int oddn = 0;
    for(int i=1; i<=n; ++i) {
        if(du[i]&1) oddn++;
    }

    if(oddn==0 || oddn==2) {
        puts("Possible");
    } else {
        puts("Impossible");
    }
    return 0;
}


hash

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;

const int maxn = 251000;
int du[maxn], f[maxn];
int n;
int findset(int x) {
    return x==f[x]?x:f[x]=findset(f[x]);
}

void Union(int a, int b) {
    if(f[a]==-1) f[a] = a;
    if(f[b]==-1) f[b] = b;
    int pa = findset(f[a]);
    int pb = findset(f[b]);
    if(pa!=pb)
        f[pa] = pb;
}

// BKDR Hash Function
int Hash(char str[]) {
    unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
    unsigned int hash = 0;
    while (*str) {
        hash = hash * seed + (*str++);
    }
    return (hash & 0x7FFFFFFF) % maxn;
}

int main() {
    char str1[20], str2[20];

    memset(du, 0, sizeof du );
    memset(f, -1, sizeof f );
    while(~scanf("%s %s", str1, str2)) {
        int a = Hash(str1);
        int b = Hash(str2);
        du[a]++;
        du[b]++;
        Union(a, b);
    }

    int cnt_root = 0;
    for(int i=1; i<maxn; ++i) {
        if(f[i]!=-1) {
            if(f[i]==i) cnt_root++;
        }
    }
    if(cnt_root >1) {
        puts("Impossible");
        return 0;
    }

    int oddn = 0;
    for(int i=1; i<maxn; ++i) {
        if(f[i]!=-1 && du[i]&1) oddn++;
    }

    if(oddn==0 || oddn==2) {
        puts("Possible");
    } else {
        puts("Impossible");
    }
    return 0;
}



你可能感兴趣的:(poj 2513 Colored Sticks,无向欧拉图的判定,Trie,hash)