• 明辨是非 [并查集+启发式合并]


    明辨是非


    color{blue}{最初想法}

    • 相等有传递性

    • 不相等没有传递性

    • 使用 并查集 维护两两之间相等的数字

    • 对每个祖先开一个 setset, 当两个数字不能相等时, 他们的祖先setset互相记录对方的祖先.

    考试的时候忘了合并 …


    color{red}{正解部分}

    • 判断是否相等时, 直接看两者的 祖先setset 中有没有记录对方 .
      若两者可以相等, 则 启发式合并 二者 setset .

    判断不等直接看祖先是否相等就可以了 .

    所谓启发式合并, 就是将 sizesize 小的合并到 sizesize 大的 .


    color{red}{实现部分}

    没什么好说的 .

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1e5 + 5;
    
    int N;
    int cnt;
    int F[maxn];
    
    std::map <int, int> Mp;
    std::set <int> st[maxn];
    
    int Find(int x){ return F[x]==x?x:F[x]=Find(F[x]); }
    
    void Work(){
            int x = read(), y = read(), p = read();
            if(!Mp.count(x)) Mp[x] = ++ cnt, F[cnt] = cnt;
            if(!Mp.count(y)) Mp[y] = ++ cnt, F[cnt] = cnt;
            int t1 = Mp[x], t2 = Mp[y];
            if(p == 1){
                    int f1 = Find(t1), f2 = Find(t2);
                    if(f1 == f2){ printf("YES
    "); return ; }
                    if(st[f1].count(f2) || st[f2].count(f1)){ printf("NO
    "); return ; }
    
                    if(st[f1].size() > st[f2].size()) std::swap(f1, f2); 
                    
                    for(reg std::set<int>::iterator i = st[f1].begin(); i != st[f1].end(); i ++) st[f2].insert(*i), st[*i].insert(f2);
    
                    F[f1] = f2;
                    printf("YES
    ");
            }else{
                    int f1 = Find(t1), f2 = Find(t2);
                    if(f1 == f2){ printf("NO
    "); return ; }
    
                    st[f1].insert(f2), st[f2].insert(f1);
    
                    printf("YES
    ");
            }
    }
    
    int main(){
            N = read();
            for(reg int i = 1; i <= N; i ++) Work();
            return 0;
    }
    
  • 相关阅读:
    hdu2844 Coins -----多重背包+二进制优化
    bzoj1452 [JSOI2009]Count ——二维树状数组
    cf685 div2 abcde
    cf675 div2 abcd
    cf669 div2 abcd
    cf668 div2 abcd
    UVA-10795
    cf665 div2 abcd
    Colored Cubes UVALive
    Image Is Everything UVALive
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822534.html
Copyright © 2020-2023  润新知