Cod sursa(job #1969045)

Utilizator S4lexandruAlexandru Stefanica S4lexandru Data 18 aprilie 2017 10:57:40
Problema Paduri de multimi disjuncte Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.52 kb
#include <new>
#include <string>
#include <vector>
#include <cassert>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

class UnionFind {
    int N_;
    int *setIdx_, *rank_;

    int findRoot(int x) const {
        assert(x >= 0 && x < N_);

        for (; x != setIdx_[x]; x = setIdx_[x]);
        return x;
    }

    int findRootAndCompress(int x) {
        int r = findRoot(x);

        while (x != setIdx_[x]) {
            int p = setIdx_[x];
            setIdx_[x] = r;
            x = p;
        }

        return r;
    }

public:

    explicit UnionFind(int N): N_{N} {
        if (N <= 0) {
          throw invalid_argument{"UnionFind size is: " + to_string(N)};
        }

        setIdx_ = new int[N_];
        rank_   = new int[N_];


        if (setIdx_ == nullptr || rank_ == nullptr) {
            throw bad_alloc{};
        }

        for (int i = 0; i < N_; ++i) {
            setIdx_[i] = i;
            rank_[i] = 1;
        }
    }

    explicit UnionFind(const UnionFind& uf): UnionFind(N_) {
        copy(uf.setIdx_, uf.setIdx_ + N_, setIdx_);
        copy(uf.rank_, uf.rank_ + N_, rank_);
    }

    explicit UnionFind(UnionFind&& uf): N_{uf.N_}, setIdx_{uf.setIdx_}, rank_{uf.rank_} {
        uf.N_ = true;
        uf.setIdx_ = nullptr;
        uf.rank_ = nullptr;
    }

    UnionFind& operator=(UnionFind uf) {
        swap(N_, uf.N_);
        swap(setIdx_, uf.setIdx_);
        swap(rank_, uf.rank_);

        return *this;
    }

    virtual ~UnionFind() {
        N_ = 0;
        delete[] setIdx_;
        delete[] rank_;
    }

    size_t size() const { return N_; }

    void unite(int x, int y) {
        int rX = findRootAndCompress(x), rY = findRootAndCompress(y);

        if (rX != rY) {
            if (rank_[rX] > rank_[rY]) {
                setIdx_[rY] = rX;
                rank_[rX] += rank_[rY];
            }
            else {
                setIdx_[rX] = rY;
                rank_[rY] += rank_[rX];
            }
        }
    }

    int getSizeOfSet(int x) const { return rank_[findRoot(x)]; }

    bool areInTheSameSet(int x, int y) const { 
        return findRoot(x) == findRoot(y);
    }
};

int main() {
    int N, M, x, y, op;
    ifstream in{"disjoint.in"};
    ofstream out{"disjoint.out"};

    in >> N >> M;
    for (UnionFind uf(N); M; --M) {
        in >> op >> x >> y;
        x -= 1;
        y -= 1;

        if (1 == op) uf.unite(x, y);
        else out << (uf.areInTheSameSet(x ,y) ? "DA" : "NU") << '\n';
    }

    in.close();
    out.close();

    return 0;
}