Submission #508326

#TimeUsernameProblemLanguageResultExecution timeMemory
508326KoDLogičari (COCI21_logicari)C++17
110 / 110
103 ms15904 KiB
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < n; ++i)

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

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)...);
    }
};

constexpr int inf = std::numeric_limits<int>::max() / 4;

void setmin(int& x, const int y) {
    if (x > y) {
        x = y;
    }
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int N;
    std::cin >> N;
    vector<vector<int>> graph(N);
    vector<int> deg(N);
    for (int i = 0; i < N; ++i) {
        int a, b;
        std::cin >> a >> b;
        a -= 1, b -= 1;
        graph[a].push_back(b);
        graph[b].push_back(a);
        deg[a] += 1, deg[b] += 1;
    }
    std::queue<int> que;
    for (int i = 0; i < N; ++i) {
        if (deg[i] == 1) {
            que.push(i);
        }
    }
    vector<vector<int>> child(N);
    while (!que.empty()) {
        const int u = que.front();
        que.pop();
        for (const int v : graph[u]) {
            if (deg[v] >= 2) {
                child[v].push_back(u);
            }
            deg[v] -= 1;
            if (deg[v] == 1) {
                que.push(v);
            }
        }
    }
    vector<int> cycle;
    for (int i = 0; i < N; ++i) {
        if (deg[i] >= 2) {
            RecLambda([&](auto&& dfs, const int u) -> void {
                deg[u] = 0;
                cycle.push_back(u);
                for (const int v : graph[u]) {
                    if (deg[v] >= 2) {
                        dfs(v);
                    }
                }
            })(i);
        }
    }
    vector<array<array<int, 2>, 2>> tree;
    for (const int r : cycle) {
        tree.push_back(RecLambda([&](auto&& dfs, const int u) -> array<array<int, 2>, 2> {
            array<array<int, 2>, 2> dp = {};
            rep(i, 2) rep(j, 2) dp[i][j] = inf;
            dp[0][0] = 0, dp[1][0] = 1;
            for (const int v : child[u]) {
                const auto add = dfs(v);
                array<array<int, 2>, 2> next = {};
                rep(i, 2) rep(j, 2) next[i][j] = inf;
                rep(i, 2) rep(j, 2) rep(k, 2) {
                    if (j and k) continue;
                    setmin(next[i][j or k], dp[i][j] + add[k][!i]);
                }
                dp = std::move(next);
            }
            return dp;
        })(r));
    }
    const int n = tree.size();
    int ans = inf;
    rep(x, 2) rep(y, 2) rep(z, 2) rep(w, 2) {
        if (y and z) continue;
        if (x and w) continue;
        array<array<int, 2>, 2> dp = {};
        rep(i, 2) rep(j, 2) dp[i][j] = inf;
        dp[z][x or w] = tree[0][x][y] + tree[1][z][w];
        for (int u = 2; u < n; ++u) {
            array<array<int, 2>, 2> next = {};
            rep(i, 2) rep(j, 2) next[i][j] = inf;
            rep(i, 2) rep(j, 2) rep(k, 2) rep(l, 2) {
                if (j == k) continue;
                if (i and l) continue;
                setmin(next[k][l or i], dp[i][j] + tree[u][k][l]);
            }
            dp = std::move(next);
        }
        rep(i, 2) rep(j, 2) {
            if (j == x) continue;
            if (i + y + z != 1) continue;
            setmin(ans, dp[i][j]);
        }
    }
    std::cout << (ans == inf ? -1 : ans) << '\n';
    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...