zoukankan      html  css  js  c++  java
  • 2020牛客多校第五场 B.Graph tire树+最小异或生成树+分治

    https://ac.nowcoder.com/acm/contest/5670/B

    题意:

    给出一个n个顶点,n-1条边的树,每条边都有一个值;

    现在有两个操作,增加一条边和删掉一条边,任何时候都满足以下要求:

    1.图连通;

    2.图中的所有环满足,每个环的边权异或和为0; 

    求图中所有边的边权最小和。

    思路:

    (全是别人的博客                

    最大异或对:https://www.acwing.com/problem/content/description/145/ 

     几乎原题: cf888G:https://blog.csdn.net/zhazhaxiaosong/article/details/107682944

     本题参考博客:https://blog.csdn.net/zhazhaxiaosong/article/details/107686336

    官方题解:

     

    总结:边权化点权,建tire树,求最小异或生成树(分治实现)

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const long long mod =1e9+7;
    typedef long long ll;
    const int inf =0x3f3f3f3f;
    const long long INF =0x3f3f3f3f3f3f3f3f;
    const int MAXN =2e6+5;
    typedef pair<int,ll>pii;
    ll a[MAXN];
    int son[MAXN][2],idx=0;
    int l[MAXN],r[MAXN];
    vector<pii>g[MAXN];
    void Insert(ll x,int id)
    {
        int p=0;
        for(int i=32;i>=0;i--)
        {
            int s=x>>i&1;
            if(!son[p][s])son[p][s]=++idx;
            p=son[p][s];
            if(!l[p])l[p]=id;
            r[p]=id;
        }
    }
    ll query(int p,int pos,ll x)
    {
        ll res=0;
        for(int i=pos;i>=0;i--)
        {
            int s=x>>i&1;
            if(son[p][s])p=son[p][s];
            else
            {
                res+=(1<<i);
                p=son[p][!s];
            }
        }
        return res;
    }
    ll solve(int p,int pos)
    {
        if(son[p][0]&&son[p][1])
        {
            int x=son[p][0],y=son[p][1];
            ll minn=1e17;
            for(int i=l[x];i<=r[x];i++)minn=min(minn,query(y,pos-1,a[i])+(1<<pos));
            return minn+solve(son[p][0],pos-1)+solve(son[p][1],pos-1);
    
        }
        else if(son[p][0])return solve(son[p][0],pos-1);
        else if(son[p][1])return solve(son[p][1],pos-1);
        return 0;
    }
    void dfs(int u,int fa)
    {
        for(auto v:g[u])
        {
            if(v.first==fa)continue;
            a[v.first]=a[u]^v.second;
            dfs(v.first,u);
        }
    }
    int main()
    {
    
        int n;
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int u,v;
            ll w;
            scanf("%d%d%lld",&u,&v,&w);
            u++,v++;
            g[u].push_back({v,w});
            g[v].push_back({u,w});
        }
        dfs(1,-1);
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++)Insert(a[i],i);
        printf("%lld
    ",solve(0,32));
        return 0;
    }
    View Code
  • 相关阅读:
    combobox获取dataset部分数据的方法
    vs2008设置Jquery自动感知方法
    iOS7 初体验
    数据采集[即与 WEB 相关的功能函数]
    javascript 时间倒计时效果
    有进度条圆周率计算
    python科学计算库
    python随笔
    jieba库
    数据分析模块pandas
  • 原文地址:https://www.cnblogs.com/MZRONG/p/13429533.html
Copyright © 2011-2022 走看看