poj 2513 Colored Sticks (字典树+并查集判连通)

本文探讨了Trie树与并查集在特定场景下的应用,通过实例展示了如何利用这两种数据结构解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>

typedef struct TrieNode{
    struct TrieNode *next[27];
    int flag;
    int id;
}Trie;

int n , tot;
Trie tree[5100005];
int father[510005];
int rank[510005];
int in[510005];
int out[510005];

void Make_Set(int x){

    father[x] = x;
    rank[x] = 0;

    return ;
}

int Find_Set(int x){
    if(x != father[x]){
        father[x] = Find_Set(father[x]);
    }
    return father[x];
}

void Union(int x , int y){

    x = Find_Set(x);
    y = Find_Set(y);
    if(x == y) return ;
    if(rank[x] > rank[y]){
        father[y] = x;
    }
    else{
        if(rank[x] == rank[y]){
            rank[y] ++;
        }
        father[x] = y;
    }

    return ;
}

void init(){

    for(int i = 0 ; i < 510005 ; i ++){
        Make_Set(i);
    }

    tot = 0;
    Trie *p = &tree[0];
    for(int i = 0 ; i < 27 ; i ++){
        p -> next[i] = NULL;
    }
    p -> flag = 0;
    p -> id = -1;

    return ;
}

int insert(Trie *root , char *s){

    int len = strlen(s);
    int j = 0 ;
    Trie *p = root;
    while(s[j]){

        if(p -> next[s[j] - 'a'] == NULL){
            Trie *temp = &tree[n ++];
            for(int i = 0 ; i < 27 ; i ++){
                temp -> next[i] = NULL;
            }
            temp -> flag = 1;
            p -> next[s[j] - 'a'] = temp;
            p = temp;
            p -> id = -1;
        }
        else{
            p = p -> next[s[j] - 'a'];
            p -> flag = 1;
        }
        j ++;

    }
    if(p -> id == -1){
        p ->id = tot;
        tot ++;
    }
    return p -> id;
}



int main(){


    int cases;
    bool flag;
    Trie *root = &tree[0];
    n = 1;
    char t1[11] , t2[11];
    memset(in , 0 , sizeof(in));
    memset(out , 0 , sizeof(out));
    int t;

    init();
    while(~scanf("%s%s" , t1 , t2)){
        t = 0;
        int a = insert(root , t1);
        int b = insert(root , t2);
        Union(a , b);
        in[a] ++;
        in[b] ++;
    }
    int cnt = 0;
    for(int i = 0 ; i < tot ; i ++){
        if(father[i] == i) cnt ++;
    }
    if(cnt == 1) flag = true;
    else flag = false;


    for(int i = 0 ; i < tot ; i ++){
        if(in[i] % 2 == 1) t ++;
    }

    if(tot == 0){
        printf("Possible\n");
    }
    else{

        if(flag == false){
            printf("Impossible\n");
        }
        else{
            if(t == 0 || t == 2){
                printf("Possible\n");
            }
            else{
                printf("Impossible\n");
            }
        }
    }



    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值