"蔚来杯"2022牛客暑期多校训练营1 J Serval and Essay
启发式合并 对于任意入度为1的点,选择它的前驱进行染色一定优于对它本身染色,于是将这两点进行合并(_Merge部分) 合并的方向由两个点的出度决定,由出度小的点向出度大的点进行合并(这样最多只有n/2条要合并的边) 合并的过程中,可能会出现入度变为1的点,进行类似深搜的操作即可
#include<bits/stdc++.h> using namespace std; #define fr first #define se second #define et0 exit(0); #define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++) #define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --) typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; typedef unsigned long long ULL; const int INF = 0X3f3f3f3f, N = 2e5 + 10, MOD = 1e9 + 7; const double eps = 1e-7; int n; int fa[N], sz[N]; set<int> from[N], to[N]; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } void _Merge(int x, int y) { x = find(x), y = find(y); if (x == y) return; if (to[x].size() < to[y].size()) swap(x, y); fa[y] = x, sz[x] += sz[y]; vector<PII> mg; for (auto u : to[y]) { to[x].insert(u); from[u].erase(y); from[u].insert(x); if (from[u].size() == 1) mg.push_back({x, u}); } for (auto u : mg) _Merge(u.fr, u.se); } void work() { cin >> n; rep(i, 1, n) from[i].clear(), to[i].clear(); rep(i, 1, n) fa[i] = i, sz[i] = 1; rep(i, 1, n) { int k; cin >> k; rep(j, 1, k) { int y; cin >> y; from[i].insert(y); to[y].insert(i); } } rep(i, 1, n) if (from[i].size() == 1) _Merge(*from[i].begin(), i); int res = 0; rep(i, 1, n) res = max(res, sz[i]); cout << res << endl; } signed main() { int test = 1, tt = 1; cin >> test; while (test--) { printf("Case #%d: ", tt++); work(); } return 0; }
本文作者:xhy666
本文链接:https://www.cnblogs.com/xhy666/p/16515606.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步