Codeforces Round #683 (Div. 2, by Meet IT) 全文见:https://blog.csdn.net/qq_43461168/article/details/113175011
E. Xor Tree
题意:
一个数组。每个元素会和与自己异或值最小的数连一条无向边。想要最终形成的图是一颗树。 至少要删掉几个元素。
思路:
首先肯定不会形成环。
为什么呢。因为一个值,只会和一个异或起来最小的值相连。要形成环。就说明至少要有一个元素。同时连向两个元素。这显然不符合条件。环中边的数量等于点的数量。但是题目的条件中。必然至少存在一对。两两异或互为最小的。也就减少了一条边。所以不可能形成环。
既然不会形成环,还有一种不是树的情况。就是形成了森林。或者说多个连通块。比如数组中 a-b 异或起来互为最小。 c-d异或起来互为最小。这时候就必须要删点了。
具体怎么删。考虑贪心。
建一颗01字典树。那么和自己异或以来最小的数。一定是同一颗子树上的,公共前缀越长越好啊,这样高位都是0。低位才会出现1。
然后就会发现,如果,一个点的左右两颗子树。都存在超过两个叶节点。那么完了。左子树的点互相连接形成连通块。右子树的点互相连接形成连通块。而左右子树 不会连边,也就是不连通。那就不可能形成树了。
所以这时候必须抉择。其中一颗子树。最多只能有一个叶子节点。其他的得删掉,那因为要贪心的考虑。肯定是选择,叶子数量大的那一颗留下来。小的那一颗删到剩下一个点就行了。
递归处理整颗树。就完成了。
AC代码:
#include <iostream>
#include <bits/stdc++.h>
#include <unordered_map>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N =