zoukankan      html  css  js  c++  java
  • B Graph(异或MST)

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

    题意:给定初始树[u,v,w],可以对树进行增加任意权重边,和删除任意边,前提是这个过程中图要保证连通且若有环则要保证环异或和为0

    分析:可以发现任意两个点之间连边的权值都是固定的。由于图始终联通,所以两点间始终存在至少一条 路径,如果存在多条,根据环的异或和为0,两点间的路径的异或和应该相等,且始终是固定的。 

       将点权转化为边权,具体就是dfs从根到节点i的路径异或和。因为这样在套入trie树时,若选择连接节点u,v,那么权重就是根节点到u的异或和 异或上 根节点到v的异或和,这样就可表示要连接u,v的权重要是u到v的路径异或和(为了达到”保证环异或和为0“这个条件)

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define MP make_pair
    typedef long long ll;
    const int mod=1e9+7;
    const int M=1e5+5;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18;
    int a[M],trie[M*32][2];
    int pos[M*32];
    vector<int>v[M];
    int tot=1;
    ll ans=0;
    struct node{
        int v,w;
    };
    vector<node>g[M];
    void pn(){
        cout<<"NO"<<'
    ';
    }
    void py(){
        cout<<"YES"<<'
    ';
    }
    void dfs1(int u,int fa){
        for(auto it:g[u]){
            if(it.v==fa)
                continue;
            a[it.v]=a[u]^it.w;
            dfs1(it.v,u);
        }
    }
    void add(int x,int id){
        int now=1;
        for(int i=30;i>=0;i--){
            if(!trie[now][(1&(x>>i))])
                trie[now][(1&(x>>i))]=++tot;
            now=trie[now][(1&(x>>i))];
        }
        pos[now]=id;
        v[id].pb(x);
    }
    ll query(int x,int rt,int dep){
        ll res=1<<dep;
        for(int i=dep-1;i>=0;i--){
            int nex=trie[rt][(1&(x>>i))];
            if(!nex){
                nex=trie[rt][1^(1&(x>>i))];
                res|=(1<<i);
            }
            rt=nex;
        }
        return res;
    }
    void dfs(int rt,int dep){
        if(!rt||!dep)
            return ;
        int lson=trie[rt][0];
        int rson=trie[rt][1];
        dfs(lson,dep-1);
        dfs(rson,dep-1);
        if(!lson||!rson){///没有分支了,说明只剩一个集合了
            pos[rt]=pos[lson+rson];
            return ;
        }
        int rid=pos[rson],lid=pos[lson];
        if(v[rid].size()>v[lid].size()){
            swap(rid,lid);
            swap(rson,lson);
        }
        ll tmp=1<<30;
        int m=v[rid].size();
        for(int i=0;i<m;i++){
            tmp=min(tmp,query(v[rid][i],lson,dep-1));
            v[lid].pb(v[rid][i]);
        }
        v[rid].clear();
        ans+=tmp;
        pos[rt]=lid;
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int u,v,w,i=1;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            u++,v++;
            g[u].pb(node{v,w});
            g[v].pb(node{u,w});
        }
        dfs1(1,0);
        sort(a+1,a+1+n);
        add(a[1],1);
        for(int i=2;i<=n;i++){
            if(a[i-1]!=a[i])
                add(a[i],i);
        }
        dfs(1,31);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    tcp_wrapper
    iptables
    Openstack_后端存储平台Ceph
    Openstack_O版(otaka)部署_Horizon部署
    Openstack_O版(otaka)部署_网络服务Neutron部署
    Openstack_O版(otaka)部署_Nova部署
    Openstack_O版(otaka)部署_镜像服务glance部署
    Openstack_O版(otaka)部署_认证服务keystone部署
    Openstack_O版(otaka)部署_准备环境和依赖软件
    模块
  • 原文地址:https://www.cnblogs.com/starve/p/13409160.html
Copyright © 2011-2022 走看看