Submission #698220

#TimeUsernameProblemLanguageResultExecution timeMemory
698220mdbrnowskiLove Polygon (BOI18_polygon)C++17
75 / 100
225 ms28204 KiB
#include <bits/stdc++.h>
using namespace std;

typedef vector<int> vi;

void change_edge(int a, int b, int c, vi& graph, vector<vi>& rgraph) {
    // a -> b    -->    a -> c
    graph[a] = c;
    rgraph[c].push_back(a);
    rgraph[b].erase(find(rgraph[b].begin(), rgraph[b].end(), a));
}

void dfs(int v, int prev, vector<vi>& rgraph, vi& dp_nope, vi& dp_yup) {
    dp_yup[v] = 0;
    int nope_minus_yup = 0;
    for (auto u : rgraph[v]) {
        if (u == prev) continue;  // important only for the first call
        dfs(u, v, rgraph, dp_nope, dp_yup);
        dp_yup[v] += dp_nope[u];
        nope_minus_yup = max(nope_minus_yup, dp_nope[u] - dp_yup[u]);
    }
    dp_nope[v] = 1 + dp_yup[v] - nope_minus_yup;
}

int calc(int start, vi& graph, vector<vi>& rgraph, vi& dp_nope, vi& dp_yup) {
    if (start == graph[start]) {
        dfs(start, graph[start], rgraph, dp_nope, dp_yup);
        return dp_nope[start];
    }
    dfs(graph[start], start, rgraph, dp_nope, dp_yup);
    dfs(start, graph[start], rgraph, dp_nope, dp_yup);
    return dp_yup[start] + dp_yup[graph[start]];
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n;
    cin >> n;
    map<string,int> names;
    int cur_name = 0;
    vi graph(n);
    vector<vi> rgraph(n);
    int res = 0;
    for (int i = 0; i < n; i++) {
        string a, b;
        cin >> a >> b;
        if (names.find(a) == names.end()) names[a] = cur_name++;
        if (names.find(b) == names.end()) names[b] = cur_name++;
        int A = names[a], B = names[b];
        graph[A] = B;
        rgraph[B].push_back(A);
    }
    if (n & 1) { cout << -1 << '\n'; return 0; }

    vi cycle_starters;
    int cc_number = 1;
    vi visited(n, 0);
    for (int i = 0; i < n; i++) {
        if (visited[i]) continue;
        visited[i] = cc_number;
        int j = graph[i];
        while (visited[j] == 0) {
            visited[j] = cc_number;
            j = graph[j];
        }
        if (visited[j] == cc_number)
            cycle_starters.push_back(j);
        cc_number++;
    }

    vi dp_nope(n),  // min number of arrows in subtree with root v if (v -> ) is changed
       dp_yup(n);   // min number of arrows in subtree with root v
    for (auto u : cycle_starters) {
        int cc_res = 1e9;
        int v = graph[u],
            w = graph[v],
            x = graph[w];
        if (u == v || u == w)
            cc_res = calc(v, graph, rgraph, dp_nope, dp_yup);
        else {
            change_edge(w, x, v, graph, rgraph);
            cc_res = min(cc_res, 1 + calc(v, graph, rgraph, dp_nope, dp_yup));
            change_edge(w, v, x, graph, rgraph);
            change_edge(v, w, u, graph, rgraph);
            cc_res = min(cc_res, 1 + calc(v, graph, rgraph, dp_nope, dp_yup));
            change_edge(v, u, w, graph, rgraph);
        }
        res += cc_res;
    }
    cout << res << '\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...