제출 #1054605

#제출 시각아이디문제언어결과실행 시간메모리
1054605cot7302Love Polygon (BOI18_polygon)C++17
100 / 100
49 ms15768 KiB
#include <bits/stdc++.h>
#define ALL(X) begin(X), end(X)
using namespace std;
using i64 = long long;

template <class T>
using vec = vector<T>;

vec<int> get_input(int n) {
    unordered_map<string, int> id;
    auto get_id = [&](const string& str) -> int {
        if (auto it = id.find(str); it != end(id))
            return it->second;
        int sz = size(id);
        return id[str] = sz;
    };
    vec<int> ret(n);
    for (int i = 0; i < n; i++) {
        string s, t; cin >> s >> t;
        ret[get_id(s)] = get_id(t);
    }
    return ret;
}

constexpr int inf = 1e9;

void solve1(int n) {
    if (n % 2 == 1)
        return void(cout << "-1\n");
    vec<int> to = get_input(n);
    vec<int> dp(1 << n, inf);
    dp[0] = 0;
    for (int mask = 1; mask < (1 << n); mask++) if (__builtin_popcount(mask) % 2 == 0) {
        for (int i = 0; i < n; i++) if ((mask >> i) & 1) {
            for (int j = 0; j < i; j++) if ((mask >> j) & 1) {
                dp[mask] = min(dp[mask], dp[mask ^ (1 << i) ^ (1 << j)] + (to[i] != j) + (to[j] != i));
            }
        }
    }
    cout << dp.back() << '\n';
}

void solve2(int n) {
    if (n % 2 == 1)
        return void(cout << "-1\n");
    vec<int> to = get_input(n);
    vec<bool> is_cir(n);
    vec<int> indeg(n), rt(n), sz(n);
    for (int i = 0; i < n; i++)
        ++indeg[to[i]];
    vec<vec<int>> G(n);
    {
        queue<int> q;
        for (int i = 0; i < n; i++)
            if (indeg[i] == 0)
                q.emplace(i);
        while (!empty(q)) {
            int x = q.front(); q.pop();
            G[to[x]].emplace_back(x);
            if (--indeg[to[x]] == 0)
                q.emplace(to[x]);
        }
    }
    vec<array<int, 2>> max_pair(n);
    for (int i = 0; i < n; i++) if (indeg[i]) {
        for (int x = i; indeg[x]; x = to[x]) {
            is_cir[x] = true;
            indeg[x] = 0;
            ++sz[i];
            auto dfs = [&](auto&& f, int y) -> void {
                rt[y] = x;
                for (auto nxt : G[y]) {
                    f(f, nxt);
                    max_pair[y][0] += max_pair[nxt][1];
                }
                for (auto nxt : G[y]) {
                    max_pair[y][1] = max(max_pair[y][1], max_pair[y][0] - max_pair[nxt][1] + max_pair[nxt][0] + 1);
                }
            };
            dfs(dfs, x);
            rt[x] = i;
        }
    }
    vec<array<int, 2>> dp0(n), dp1(n);
    vec<int> ans(n);
    for (int i = 0; i < n; i++) if (rt[i] == i) {
        if (sz[i] == 2) {
            ans[i] = 2 + max_pair[i][0] + max_pair[to[i]][0];
        }
        dp0[i][0] = max_pair[i][0];
        dp0[i][1] = -inf;
        dp1[i][0] = max_pair[i][0];
        dp1[i][1] = max_pair[i][1];
        int pre = i;
        for (int x = to[i], cnt = 1; cnt < sz[i]; x = to[x], ++cnt) {
            dp1[x][0] = max_pair[x][0] + dp1[pre][1];
            dp1[x][1] = max(max_pair[x][1] + dp1[pre][1], max_pair[x][0] + dp1[pre][0] + 1);
            if (pre != i) {
                dp0[x][0] = max_pair[x][0] + dp0[pre][1];
                dp0[x][1] = max(max_pair[x][1] + dp0[pre][1], max_pair[x][0] + dp0[pre][0] + 1);
            }
            else {
                dp0[x][0] = max_pair[x][0] + dp0[pre][0];
                dp0[x][1] = max(max_pair[x][1] + dp0[pre][0], max_pair[x][0] + dp0[pre][0]);
            }
            if (cnt == sz[i] - 1) {
                ans[i] = max({ans[i], dp0[x][1], dp1[x][0], dp1[x][1]});
                ans[i] = max(ans[i], dp0[x][0] + 1);
            }
            pre = x;
        }
        if (sz[i] == 1)
            ans[i] = max(max_pair[i][0], max_pair[i][1]);
    }
    int tot{};
    for (int i = 0; i < n; i++)
        if (rt[i] == i)
            tot += ans[i];
    cout << n - tot << '\n';
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n; cin >> n;
    /*if (n <= 20) solve1(n);
    else */solve2(n);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...