zoukankan      html  css  js  c++  java
  • poj2513--并查集+欧拉路+字典树

    经典好题,自己不知道哪里错了交上去是RE,可能是数组开的不好吧,字典树老碰到这种问题。。

    先马上别人的代码,有空对拍看看

    #include <cstdio>
    #include <cstring>
    int const MAX = 500005;
    int fa[MAX], d[MAX], cnt;
     
    struct Trie
    {
        int sz, t[MAX][15];
        int jud[MAX];
        Trie()
        {
            sz = 1;
            memset(t[0], -1, sizeof(t));
            jud[0] = 0;
        }
        void clear()
        {
            sz = 1;
            memset(t[0], -1, sizeof(t));
            jud[0] = 0;
        }
        int idx(char c)
        {
            return c - 'a';
        }
        void insert(char* s, int v)
        {
            int u = 0, len = strlen(s);
            for(int i = 0; i < len; i++)
            {
                int c = idx(s[i]);
                if(t[u][c] == -1)
                {
                    memset(t[sz], -1, sizeof(t[sz]));
                    jud[sz] = 0;
                    t[u][c] = sz++;
                }
                u = t[u][c];
            }
            jud[u] = v;
        }
        int search(char* s)
        {
            int u = 0, len = strlen(s);
            for(int i = 0; i < len; i++)
            {
                int c = idx(s[i]);
                if(t[u][c] == -1) 
                    return -1;
                u = t[u][c];
            }
            if(jud[u]) 
                return jud[u];
            return -1;
        }
    }t;
     
     
    void Init()
    {
        for(int i = 0; i < MAX; i++)
            fa[i] = i;
    }
     
    int Find(int x)
    {
        return x == fa[x] ? x : fa[x] = Find(fa[x]);
    }
     
    void Union(int a, int b)
    {
        int r1 = Find(a);
        int r2 = Find(b);
        if(r1 != r2)
            fa[r1] = r2;
    }
     
    bool eluer()
    {
        int sum = 0, t = -1;
        for(int i = 1; i < cnt; i++)
            if(d[i] % 2) 
                sum++;
        if(sum != 0 && sum != 2)
            return false;
        for(int i = 1; i < cnt; i++)
        {
            if(t == -1)
                t = Find(i);
            else if(Find(i) != Find(t)) 
                return false;
        }
        return true;
    }
     
    int main()
    {
        char s1[20],s2[20];
        cnt = 1;
        Init();
        t.clear();
        while(scanf("%s %s", s1, s2) != EOF)
        {
            if(t.search(s1) == -1)
                t.insert(s1, cnt++);
            int u = t.search(s1);
            if(t.search(s2) == -1)
                t.insert(s2, cnt++);
            int v = t.search(s2);
            Union(u, v);
            d[u]++;
            d[v]++;
        }
        if(eluer())
            printf("Possible
    ");
        else
            printf("Impossible
    ");
    }

    下面是RE代码

    /*
    1 2
    2 3
    4 1
    1 5
    5 4
    1 5,5 4,4 1,1 2,2 3 
    数据量大,不能用map
    建立字典树,保留每个颜色的id
    更新每个颜色的度,只要一个颜色的度为奇数,cnt1++
    用并查集保存图的连通性,如果最后剩下两个集,那么图不连通
    注意:每个颜色都是一个点,每根木棒连接两个颜色,这就可以看做是并查集的连接 
    500*26
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    struct Trie{
        int next[500005][15];
        int id[500005];
        int root,L,cnt;
        int newnode(){
            for(int i=0;i<15;i++)
                next[L][i]=-1;
            id[L]=0;
            return L++;
        }
        void init(){
            L=cnt=0;
            root=newnode(); 
        }
        int insert(char s[]){
    //cout << s << cnt<<endl;
            int len=strlen(s);
            int now=root;
            for(int i=0;i<len;i++){
                if(next[now][s[i]-'a']==-1)
                    next[now][s[i]-'a']=newnode();
                now=next[now][s[i]-'a'];
            }
            if(id[now]==0)
                id[now]=++cnt;
            return id[now];
        }
    }tr;
    int degree[25000*20]; 
    int F[25000*20];
    int find(int x){
        if(F[x]==-1) return x;
        return F[x]=find(F[x]);
    }
    void bing(int a,int b){
        int t1=find(a);
        int t2=find(b);
        if(t1!=t2) F[t1]=t2;
    }
    int main(){
        tr.init();
        memset(degree,0,sizeof degree);
        memset(F,-1,sizeof F);
        char s1[15],s2[15];
        while(scanf("%s%s",s1,s2)!=EOF){
            int id1=tr.insert(s1);
            int id2=tr.insert(s2);
            degree[id1]++;
            degree[id2]++;
            bing(id1,id2);
        }
        int cnt1=0,cnt2=0;//度为奇数的颜色,联通块 
        for(int i=1;i<=tr.cnt;i++){
            if(degree[i]%2==1) cnt1++;
            if(F[i]==-1) cnt2++;
            if(cnt1>2) break;
            if(cnt2>1) break;
        }
    
        if ((cnt2==0 || cnt2==1) && (cnt1==0 || cnt1==2))
            puts("Possible");
        else puts("Impossible");
        return 0;
    } 
  • 相关阅读:
    寻找重复数
    除自身以外数组的乘积
    汇总区间
    Atlas 分表功能
    Atlas 读写分离 & Atlas + MHA 故障自动恢复
    MHA 的 Binlog Server & VIP 漂移
    MHA 高可用介绍
    MySQL 主从复制(下)
    MySQL 基础面试题
    MySQL 主从复制(上)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9818671.html
Copyright © 2011-2022 走看看