Submission #403966

#TimeUsernameProblemLanguageResultExecution timeMemory
403966rama_pangLove Polygon (BOI18_polygon)C++17
29 / 100
247 ms28476 KiB
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); int N; cin >> N; vector<int> to(N); const auto GetName = [&](string s) { static map<string, int> mp; if (mp.count(s)) return mp[s]; return mp[s] = mp.size(); }; for (int i = 0; i < N; i++) { string s, t; cin >> s >> t; int u = GetName(s); int v = GetName(t); to[u] = v; } if (N & 1) { cout << -1 << '\n'; return 0; } const auto SolveTree = [&](vector<int> nodes) -> int { static vector<int> dp0(N), dp1(N); static vector<vector<int>> adj(N); int root = -1; for (auto u : nodes) { if (to[u] == u) { assert(root == -1); root = u; } else { adj[to[u]].emplace_back(u); } } const auto Dfs = [&](const auto &self, int u) -> void { // If we don't use arrow on v: // - Must use arrow on u // - Must use arrow on other children of u // - Must use arrow on children of v // dp0[u] = don't use arrow on u // dp1[u] = use arrow on u dp0[u] = 0; dp1[u] = to[u] == u ? -1e9 : 1; int sum0 = 0; for (auto v : adj[u]) { self(self, v); sum0 += dp0[v]; } dp0[u] += sum0; dp1[u] += sum0; for (auto v : adj[u]) { dp0[u] = max(dp0[u], sum0 - dp0[v] + dp1[v]); } }; Dfs(Dfs, root); return max(dp0[root], dp1[root]); }; const auto SolveForest = [&](vector<int> nodes) -> int { static vector<int> vis(N); static vector<vector<int>> adj(N); for (auto i : nodes) { adj[i].emplace_back(to[i]); adj[to[i]].emplace_back(i); } int ans = 0; for (auto i : nodes) if (!vis[i]) { vis[i] = 1; vector<int> que = {i}; for (int j = 0; j < int(que.size()); j++) { int u = que[j]; for (auto v : adj[u]) if (!vis[v]) { vis[v] = 1; que.emplace_back(v); } } ans += SolveTree(que); } return ans; }; const auto Solve = [&](vector<int> nodes) -> int { static vector<int> indeg(N); static vector<int> in_cycle(N); for (auto u : nodes) { indeg[to[u]]++; } vector<int> que; for (auto u : nodes) { if (indeg[u] == 0) { que.emplace_back(u); } } for (int i = 0; i < int(que.size()); i++) { int u = que[i]; int v = to[u]; indeg[v]--; if (indeg[v] == 0) { que.emplace_back(v); } } for (auto u : nodes) in_cycle[u] = 1; for (auto u : que) in_cycle[u] = 0; vector<int> cyc; for (auto u : nodes) if (in_cycle[u]) { cyc.emplace_back(u); } if (cyc.size() == 1) { return SolveTree(nodes); } else { int u = cyc[0]; int v = to[u]; assert(u != v); // Don't use (u, v) to[u] = u; int ans_1 = SolveTree(nodes); to[u] = v; // Use (u, v) vector<int> nn = nodes; nn.erase(find(begin(nn), end(nn), u)); nn.erase(find(begin(nn), end(nn), v)); for (auto x : nn) { if (to[x] == u || to[x] == v) { to[x] = x; } } int ans_2 = (to[u] == v) + (to[v] == u) + SolveForest(nn); return max(ans_1, ans_2); } }; int ans = 0; vector<int> vis(N); vector<vector<int>> adj(N); for (int i = 0; i < N; i++) { adj[i].emplace_back(to[i]); adj[to[i]].emplace_back(i); } for (int i = 0; i < N; i++) if (!vis[i]) { vis[i] = 1; vector<int> que = {i}; for (int j = 0; j < int(que.size()); j++) { int u = que[j]; for (auto v : adj[u]) if (!vis[v]) { vis[v] = 1; que.emplace_back(v); } } ans += Solve(que); } cout << N - 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...