cf1446 C. Xor Tree
题意:
数组中的数两两不同。对数组中的每个数 ,找数组中的另一个数 , 最小;在 间连一条无向边。(如果已经有边就不连了)
问在建图前至少要删除几个数,使得连边后的图是一棵树
思路:
先把所有数插到 01trie 里(为了方便,我的 trie 以 idx=1 号节点为根)
连边后会形成若干连通块。
在 trie 上 dfs,返回以 u 为根节点的子树中的最大连通块的大小
设 u 的俩儿子为 v0 和 v1。v0 中的最大连通块为 A,v2 中的最大连通块为 B。那么在删除 B 中的某几个数后,B 中的其他数也不可能跑到 A 里去,而只会与 v1 中的其他数连边。这是因为对 B 中一个数,B 中的另一个数和它的相同前缀长度肯定大于 A 中的数。
那么只能取某个儿子子树中的最大连通块(该儿子子树中的其他数舍弃),然后另一个儿子子树中只能取一个数。
注意 dfs 到叶子节点说明找到一个数,应该返回 1
int n, a[N];
int tr[N*30][2], idx = 1;
void ins(int x) {
int p = 1;
for(int i = 29; i >= 0; i--) {
bool u = x>>i&1;
if(!tr[p][u]) tr[p][u] = ++idx;
p = tr[p][u];
}
}
int dfs(int u) {
if(!u) return 0; //不存在该节点
int l = dfs(tr[u][0]), r = dfs(tr[u][1]);
return max(l, r) + (l && r || !l && !r); //没儿子要返回1
}
void sol() {
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i], ins(a[i]);
cout << n - dfs(1);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下