zoukankan      html  css  js  c++  java
  • Xor-MST学习/ 2020牛客暑假多校(五)B.Graph

    Xor-MST学习/ 2020牛客暑假多校(五)B.Graph

    补题链接

    题目大意:

    给一个完全图,求异或最小生成树。

    题解:

    首先先看一下这道题:CF888G 。与本题不同之处是这两个题一个给点的权值,一个给边的权值。但实际上一样可以相互转换。如让本题中a[1]= 0,跑一下dfs,算出所有点的权值就变为CF888G题了。

    处理异或,考虑使用Trie树。Trie树除了可以处理字符串外,还可以处理二进制。把点值插入Trie树,会发现,两个叶子节点的LCA越深,则它们代表的值的异或值越小(LCA相等时情况不一定)。 要使异或值最小就要尽量让高位相等,尽量走同一条路径。

    所以我们计算每一个子树的贡献,考虑启发式合并,每次做siz小的一边在字典树上取计算siz大的一边的贡献。复杂度O(nlogn)。总复杂度(O(nlog^{2}n))

    其实把CF888G那题当作一个Xor-MST模板题学会,这一题就直接是套路题了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<vector>
    #include<string>
    #include<fstream>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i)
    #define per(i, a, n) for(int i = n; i >= a; -- i)
    typedef long long ll;
    const int N = 5e6 + 105;
    const int mod = 998244353;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    //
    int n;
    ll a[N];
    int head[N], cnt = 0;
    struct node{
        int to, nxt, c;
    }edge[N];
    
    void add(int u, int v, int w){
        edge[cnt].to = v, edge[cnt].c = w, edge[cnt].nxt = head[u], head[u] = cnt ++;
        edge[cnt].to = u, edge[cnt].c = w, edge[cnt].nxt = head[v], head[v] = cnt ++;
    }
    
    struct XorTrie{
        int cnt;
        int t[N][2];
        int L[N], R[N];
        void _init(){
            cnt = 0;
        }
        void Insert(ll x, int id){
            int rt = 0;
            for(int i = 32; i >= 0; -- i){
                int op = x >> i & 1ll;
                if(!t[rt][op]) t[rt][op] = ++ cnt;
                rt = t[rt][op];
                
                if(!L[rt]) L[rt] = id;
                R[rt] = id;
            }
        }
        ll ask(int rt, int pos, ll x){
            ll res = 0;
            for(int i = pos; i >= 0; -- i){
                int op = x >> i & 1ll;
                if(t[rt][op]) rt = t[rt][op];
                else {
                    rt = t[rt][!op];
                    res += (1ll << i);
                }
            }
            return res;
        }
        
        ll query(int rt, int pos){
            if(t[rt][0] && t[rt][1]){
                int x = t[rt][0], y = t[rt][1];
                ll minn = 1e18;
                for(int i = L[x]; i <= R[x]; ++ i) 
                    minn = min(minn, ask(y, pos - 1, a[i]) + (1ll << pos));
                return minn + query(t[rt][0], pos - 1) + query(t[rt][1], pos - 1);
            }
            else if(t[rt][0]) return query(t[rt][0], pos - 1);
            else if(t[rt][1]) return query(t[rt][1], pos - 1);
            return 0;
        }
        
    }trie;
    
    
    void dfs(int u, int pre){
        for(int i = head[u] ; i != -1; i = edge[i].nxt){
            int v = edge[i].to, w = edge[i].c;
            if(v == pre) continue;
            a[v] = a[u] ^ w;
            dfs(v, u);
        }
    }
    
    int main()
    {
        memset(head, -1, sizeof(head));
        trie._init();
        scanf("%d",&n);
        for(int i = 1; i < n; ++ i){
            int x, y, z; scanf("%d%d%d",&x,&y,&z);
            x ++; y ++;
            add(x, y, z);
        }
        a[1] = 0;
        dfs(1, -1);
        sort(a + 1, a + n + 1);
        for(int i = 1; i <= n; ++ i) trie.Insert(a[i], i);
        printf("%lld
    ",trie.query(0, 32));
        return 0;
    }
    
  • 相关阅读:
    tcpprep 对IPV6的支持
    the server quit without updating pid file (/var/lib/mysql/localhost.localdomain.pid)
    servlet service() for servlet jsp throws null pointer exception
    tomcat开机启动
    mysql 允许远程访问
    spring的helloworld
    java中的那些坑
    关于struts2中的相对路径与绝对路径
    Powercenter Source Filter
    oracle删除当前用户的表
  • 原文地址:https://www.cnblogs.com/A-sc/p/13442773.html
Copyright © 2011-2022 走看看