zoukankan      html  css  js  c++  java
  • 明辨是非 [并查集+启发式合并]

    明辨是非


    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;
    }
    
  • 相关阅读:
    UVA 254 Towers of Hanoi
    UVA 701 The Archeologists' Dilemma
    UVA 185 Roman Numerals
    UVA 10994 Simple Addition
    UVA 10570 Meeting with Aliens
    UVA 306 Cipher
    UVA 10160 Servicing Stations
    UVA 317 Hexagon
    UVA 10123 No Tipping
    UVA 696 How Many Knights
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822534.html
Copyright © 2011-2022 走看看