Submission #1272468

#TimeUsernameProblemLanguageResultExecution timeMemory
1272468alphasLogičari (COCI21_logicari)C++20
10 / 110
210 ms40420 KiB
/* Burung ini cuma template ░░ ▄▀▀▀▄░░░ ▄███▀░◐░░░▌░░░░░░░ ░░░░▌░░░░░▐░░░░░░░ ░░░░▐░░░░░▐░░░░░░░ ░░░░▌░░░░░▐▄▄░░░░░ ░░░░▌░░░░▄▀▒▒▀▀▀▀▄ ░░░▐░░░░▐▒▒▒▒▒▒▒▒▀▀▄ ░░░▐░░░░▐▄▒▒▒▒▒▒▒▒▒▒▀▄ ░░░░▀▄░░░░▀▄▒▒▒▒▒▒▒▒▒▒▀▄ ░░░░░░▀▄▄▄▄▄█▄▄▄▄▄▄▄▄▄▄▄▀▄ ░░░░░░░░░░░▌▌░▌▌░░░░░ ░░░░░░░░░░░▌▌░▌▌░░░░░ ░░░░░░░░░▄▄▌▌▄▌▌░░░░░ */ #include<bits/stdc++.h> #define mp make_pair #define fs first #define sc second #define pb push_back #define debug(x) cout<<#x<<" = "<<(x)<<endl #define mod 1000000007 #define INF 1e9 #define ALPHABET_SIZE 26 using namespace std; /* Look for: * the exact constraints (multiple sets are too slow for n=10^6 :( ) * special cases (n=1?) * overflow (ll vs int?) * array bounds * if you have no idea just guess the appropriate well-known algo instead of doing nothing :/ */ vector<int> adj[100005]; int specialNode, root; long long depe[100005][2][2][2][2]; // the param for DP: now, currentColor (0/1), parentColor (0/1), rootColor (0/1), specialNodeColor (0/1) // transition: // - if currentColor = 1 (black) // - if parentColor = 1 (black), all of the child should 0 (white) // - if parentColor = 0 (white), choose 1 child that should be black // - if currentColor = 0 (white) // - if parentColor = 1 (black), all of the child should 0 (white) // - if parentColor = 0 (white), choose 1 child that should be black // // root is special (its parentColor is the specialNodeColor): // - if currentColor = 1 (black) // - if specialNodeColor = 1 (black), all of the child should 0 (white) // - if specialNodeColor = 0 (white), choose 1 child that should be black // - if currentColor = 0 (white) // - if specialNodeColor = 1 (black), all of the child should 0 (white) // - if specialNodeColor = 0 (white), choose 1 child that should be black // now == specialNode: // - if currentColor different from colorSpecialNode, return IMPOSSIBLE // - if currentColor = 1 (black), rootColor = 1, and parentColor = 1, then return IMPOSSIBLE (this special node sees 2 black) long long dp(int now, int par, int currentColor, int parentColor, int rootColor, int specialNodeColor) { if(now == specialNode) { if(currentColor != specialNodeColor) { return INF; } if(rootColor == 1 && parentColor == 1) { return INF; } } long long &ret = depe[now][currentColor][parentColor][rootColor][specialNodeColor]; if(ret != -1) return ret; // count the dp if all of his child is white, store it in whiteCost long long whiteCost[adj[now].size() + 1]; long long total = 0; for(int i = 0; i < adj[now].size(); i++) { if(adj[now][i] == par || (now == root && adj[now][i] == specialNode) || (now == specialNode && adj[now][i] == root)) continue; whiteCost[i] = dp(adj[now][i], now, 0, currentColor, rootColor, specialNodeColor); // if(rootColor == 1 && specialNodeColor == 0 && now == 1) { // cout << "now = " << now << " adj[now][i] = " << adj[now][i] << " rootColor = " << rootColor << " specialNodeColor = " << specialNodeColor << " whiteCost = " << whiteCost[i] << endl; // } total += whiteCost[i]; } // if(now == specialNode) { // cout << "SPECIAL NODE now = " << now << " currentColor = " << currentColor << " parentColor = " << parentColor << " rootColor = " << rootColor << " specialNodeColor = " << specialNodeColor << endl; // } if(parentColor == 1) { ret = total; } else { // if currentColor = 1 (black), parentColor = 0 (white), then we should choose 1 child that should be black // but if there is no child, we should return IMPOSSIBLE ret = INF; for(int i = 0; i < adj[now].size(); i++) { if(adj[now][i] == par || (now == root && adj[now][i] == specialNode) || (now == specialNode && adj[now][i] == root)) continue; int cost = 0; if(currentColor == 1) cost = 2; // exchange the color of the child[i] from white to black ret = min(ret, total - whiteCost[i] + dp(adj[now][i], now, 1, currentColor, rootColor, specialNodeColor) + cost); } } return ret; } bool vis[100005]; pair<int, int> specialEdge; void findCycle(int now, int par) { for(auto nxt : adj[now]) { if(nxt == par) continue; if(vis[nxt]) { specialEdge = {now, nxt}; return; } vis[nxt] = true; findCycle(nxt, now); } } int main(){ int n; cin >> n; for(int i = 1; i <= n; i++){ int u, v; cin >> u >> v; adj[u].pb(v); adj[v].pb(u); } // we should pick the special edge from the cycle // we should find the cycle first memset(vis, false, sizeof(vis)); vis[1] = true; findCycle(1, -1); // specialEdge = {root, specialNode} specialNode = specialEdge.second; root = specialEdge.first; // cout << "specialEdge = " << specialEdge.first << " " << specialEdge.second << endl; // 4 case for the special edge (root, specialNode): // - both of them are black // - both of them are white // - root is black, specialNode is white // - root is white, specialNode is black memset(depe, -1, sizeof(depe)); long long ans = INF; for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { int cost = 0; if(i == 1 && j == 1) { cost = 2; } ans = min(ans, dp(root, -1, i, j, i, j) + cost); // cout << "i = " << i << " j = " << j << " dp = " << dp(root, -1, i, j, i, j) + cost << endl; } } if(ans >= INF) { ans = -1; } cout << ans << endl; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...