POI2008MAF-Mafia
POI #基环树 #贪心 #Year2008
一定是若干棵基环内向树,以下仅考虑一棵的情况
最小值直接从下往上选,然后环上的为环的 的一半
最大值为 减去叶子个数,再特判环上剩下一个的情况
// Author: xiaruize const int N = 1e6 + 10; int n; int a[N]; int deg[N]; int cnt = 0, res = 0; queue<int> q; bool fl[N]; bool vis[N]; void solve() { cin >> n; rep(i, 1, n) { cin >> a[i]; deg[a[i]]++; } queue<int> q; rep(i, 1, n) { if (!deg[i]) { q.push(i); cnt++; res++; } } while (!q.empty()) { int x = q.front(); q.pop(); if (vis[a[x]]) continue; vis[a[x]] = true; deg[a[a[x]]]--; fl[a[a[x]]] = true; if (!deg[a[a[x]]]) { q.push(a[a[x]]); cnt++; } } rep(i, 1, n) { if (deg[i] && !vis[i]) { int x = i; bool f = false; int len = 0; do { f |= fl[x]; len++; vis[x] = true; x = a[x]; } while (x != i); if (!f && len > 1) res++; cnt += len / 2; } } cout << n - cnt << ' ' << n - res << endl; } #ifndef ONLINE_JUDGE bool end_of_memory_use; #endif signed main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int testcase = 1; // cin >> testcase; while (testcase--) solve(); #ifndef ONLINE_JUDGE cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl; cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl; #endif return 0; }
本文作者:xiaruize's Blog
本文链接:https://www.cnblogs.com/xiaruize/p/18136779
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步