Submission #520060

#TimeUsernameProblemLanguageResultExecution timeMemory
520060KoDMatching (COCI20_matching)C++17
58 / 110
2532 ms15600 KiB
#include <bits/stdc++.h>

using std::vector;
using std::array;
using std::pair;
using std::tuple;

constexpr int MAX = 100000;

template <class F> struct RecLambda : private F {
    explicit RecLambda(F&& f) : F(std::forward<F>(f)) {}
    template <class... Args> decltype(auto) operator()(Args&&... args) const {
        return F::operator()(*this, std::forward<Args>(args)...);
    }
};

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int N;
    std::cin >> N;
    vector<int> X(N), Y(N);
    for (int i = 0; i < N; ++i) {
        std::cin >> X[i] >> Y[i];
    }
    vector<vector<int>> graph(2 * N), revgraph(2 * N);
    const auto add_edge = [&](const int i, const int j) {
        graph[i].push_back(j);
        revgraph[j].push_back(i);
    };
    vector<pair<int, int>> vert, hori;
    vector<char> found(2 * N);
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < i; ++j) {
            if (X[i] == X[j]) {
                if (Y[i] < Y[j]) {
                    vert.emplace_back(i, j);
                } else {
                    vert.emplace_back(j, i);
                }
                for (int k = 0; k < 2; ++k) {
                    add_edge(2 * i + k, 2 * j + k);
                    add_edge(2 * j + k, 2 * i + k);
                }
                found[2 * i] = found[2 * j] = true;
            } 
            if (Y[i] == Y[j]) {
                if (X[i] < X[j]) {
                    hori.emplace_back(i, j);
                } else {
                    hori.emplace_back(j, i);
                }
                for (int k = 0; k < 2; ++k) {
                    add_edge(2 * i + k, 2 * j + k);
                    add_edge(2 * j + k, 2 * i + k);
                }
                found[2 * i + 1] = found[2 * j + 1] = true;
            }
        }
    }
    for (int i = 0; i < 2 * N; ++i) {
        if (!found[i]) {
            add_edge(i, i ^ 1);
        }
    }
    for (const auto& [u, v] : vert) {
        for (const auto& [a, b] : hori) {
            if (X[a] < X[u] and X[u] < X[b] and Y[u] < Y[a] and Y[a] < Y[v]) {
                add_edge(2 * u, 2 * a);
                add_edge(2 * a + 1, 2 * u + 1);
            }
        }
    }
    vector<char> done(2 * N);
    vector<int> stack;
    for (int i = 0; i < 2 * N; ++i) {
        RecLambda([&](auto&& dfs, const int u) -> void {
            if (done[u]) {
                return;
            }
            done[u] = true;
            for (const int v : graph[u]) {
                dfs(v);
            }
            stack.push_back(u);
        })(i);
    }
    int idx = 0;
    vector<int> group(2 * N);
    std::fill(done.begin(), done.end(), false);
    while (!stack.empty()) {
        const int u = stack.back();
        stack.pop_back();
        RecLambda([&](auto&& dfs, const int u) -> void {
            if (done[u]) {
                return;
            }
            group[u] = idx;
            done[u] = true;
            for (const int v : revgraph[u]) {
                dfs(v);
            }
        })(u);
        idx += 1;
    }
    vector<char> type(N);
    for (int i = 0; i < N; ++i) {
        if (group[2 * i] == group[2 * i + 1]) {
            std::cout << "NE\n";
            return 0;
        }
        type[i] = group[2 * i] > group[2 * i + 1];
    }
    std::cout << "DA\n";
    for (const auto& [u, v] : vert) {
        if (type[u]) {
            std::cout << u + 1 << ' ' << v + 1 << std::endl;
        }
    }
    for (const auto& [u, v] : hori) {
        if (!type[u]) {
            std::cout << u + 1 << ' ' << v + 1 << std::endl;
        }
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...