zoukankan      html  css  js  c++  java
  • [CF1446C] Xor Tree

    Description

    给定 (n) 个自然数,每个数会与自己异或最小的数,向它连一条边。求至少删去多少个数,才能使这个自然数集合经过这样的操作构成的图是一棵树。边都是无向的,重边自动合并。

    Solution

    考虑在 0-1 Trie 中,如果结点 (p) 的子树中有 (1) 个有效叶子结点,那么这个结点一定会与子树外的结点连边,因此我们可以说 (p) 的子树是安全的。

    相反地,如果 (p) 的子树内有 (ge 2) 个有效叶子结点,那么这些结点之间一定会相互匹配连边,因此 (p) 子树内的这些节点就会与剩余的部分断开。

    因此,对于一个结点 (p),它的左子树和右子树分别为 (x,y),如果两边的叶子结点数目都大于 (1),那么我们需要将一边的有效叶子结点数目删减到不超过 (1),才能使得整个过程是有效的。至于删除哪一边,需要递归做下去。

    具体地,我们定义 (f(p)) 表示结点 (p) 的子树内的有效叶子结点最多可以保留多少个。

    如果 (p) 的左子树中的有效叶子结点个数为零,那么 (f(p) = f(p.rightChild))

    如果 (p) 的右子树中的有效叶子结点个数为零,那么 (f(p) = f(p.leftChild))

    如果 (p) 的左右子树中的有效叶子结点个数都非零,那么 (f(p) = max(f(p.leftChild), p.(rightChild)) + 1),即我们将一边删除到只剩下一个。

    作为递归的边界,当子树内只有一个结点(或者层数达到叶子)的时候,返回一个值即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    
    int n;
    vector<int> a;
    
    int f(vector<int> a, int b)
    {
        if (b == -1)
            return a.size() ? 1 : 0;
        vector<int> c[2];
        for (int i : a)
            c[(i >> b) & 1].push_back(i);
        if (c[0].size() == 0)
            return f(c[1], b - 1);
        if (c[1].size() == 0)
            return f(c[0], b - 1);
        return max(f(c[0], b - 1), f(c[1], b - 1)) + 1;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            int t;
            cin >> t;
            a.push_back(t);
        }
        cout << n - f(a, 30) << endl;
    }
    
    
  • 相关阅读:
    centos安装vsftp
    php利用soap实现webservice 和利用soap调用其他语言的webservice
    php连接redis数据库 操作redis任务队列
    shopnc编译安装IM服务器node.js
    centos6.5 64位 yum install nginx的默认安装路径
    安装nfs服务器
    php扩展redis,编译安装redis服务
    x86_64编译JPEG遇到Invalid configuration `x86_64-unknown-linux-gnu'
    shopnc nginx优化配置文件
    nginx支持flv MP4 扩展nginx_mod_h264_streaming,nginx-rtmp-module-master,yamdi
  • 原文地址:https://www.cnblogs.com/mollnn/p/14013000.html
Copyright © 2011-2022 走看看