Cod sursa(job #2972936)

Utilizator HandoMihnea-Vicentiu Hando Data 30 ianuarie 2023 17:55:57
Problema Paduri de multimi disjuncte Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.85 kb
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define ar array
#define vt vector
#define pq priority_queue
#define pu push
#define pub push_back
#define em emplace
#define emb emplace_back

#define all(x) x.begin(), x.end()
#define allr(x) x.rbegin(), x.rend()
#define allp(x, l, r) x.begin() + l, x.begin() + r
#define len(x) (int)x.size()

using namespace std;
using namespace __gnu_pbds;

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <class T, size_t N>
void re(array <T, N>& x);
template <class T> 
void re(vt <T>& x);

template <class T> 
void re(T& x) {
    cin >> x;
}

template <class T, class... M> 
void re(T& x, M&... args) {
    re(x); re(args...);
}

template <class T> 
void re(vt <T>& x) {
    for(auto& it : x)
        re(it);
}

template <class T, size_t N>
void re(array <T, N>& x) {
    for(auto& it : x)
        re(it);
}

template <class T, size_t N>
void wr(array <T, N> x);
template <class T> 
void wr(vt <T> x);

template <class T> 
void wr(T x) {
    cout << x;
}

template <class T, class ...M>  void wr(T x, M... args) {
    wr(x), wr(args...);
}

template <class T> 
void wr(vt <T> x) {
    for(auto it : x)
        wr(it, ' ');
}

template <class T, size_t N>
void wr(array <T, N> x) {
    for(auto it : x)
        wr(it, ' ');
}


inline void Open(const string Name) {
    #ifndef ONLINE_JUDGE
        (void)!freopen((Name + ".in").c_str(), "r", stdin);
        (void)!freopen((Name + ".out").c_str(), "w", stdout);
    #endif
}

struct DSU {
    int n;
    vt <int> par, rnk;

    DSU() {}
    DSU(int _n) {
        n = _n;
        par.resize(n);
        rnk.resize(n);
        iota(all(par), 0);
    }

    void init(int _n) {
        n = _n;
        par.resize(n);
        rnk.resize(n);
        iota(all(par), 0);
    }

    void make_set(int u) {
        par[u] = u;
    }

    int find_set(int u) {
        if (u == par[u])
            return u;
        return par[u] = find_set(par[u]);
    }

    void union_sets(int a, int b) {
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (rnk[a] < rnk[b])
                swap(a, b);
            par[b] = a;
            if (rnk[a] == rnk[b])
                ++rnk[a];
        }
    }

    bool check_sets(int a, int b) {
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            return false;
        }
        return true;
    }

};

void solve() {
    /* DSU
       The basic interface of this data structure consists of only three operations:
       make_set(v) := creates a new set consisting of the new element v
       union_set(a, b) := merges the two specified sets (the set in which the element a is located, and the set in which the element b is located)
       find_set(v) := returns the representative (also called leader) of the set that contains the element v. This representative is an element of its corresponding set.
       It is selected in each set by the data structure itself (and can change over time, namely after union_sets calls). 
       This representative can be used to check if two elements are part of the same set or not. a and b are
       actly in the same set, if find_set(a) == find_set(b). Otherwise they are in different sets.
    */

    int n, m; re(n, m);
    DSU T(n);

    for (int i = 0; i < m; ++i) {
        int task, a, b; re(task, a, b);
        --a, --b;
        if (task == 1) {
            T.union_sets(a, b);
            continue;
        }
        wr(T.check_sets(a, b)? "DA\n" : "NU\n");
    }

}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    Open("disjoint");

    int t = 1;
    for(;t;t--) {
        solve();
    }
    
    return 0;
}