【Nowcoder - 5670 B Graph】2020 牛客暑期多校训练营(第五场)【最小异或生成树、Boruvka 思想】
前言
如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。
题意
给定一颗 nnn 个点的树,每条边的权重为 wiw_iwi。(2≤n≤105,0≤wi<230)(2\leq n\leq 10^5,0\leq w_i< 2^{30})(2≤n≤105,0≤wi<230)
可以任意删除一些边或者增加一些边,但是在删增过程中必须保证图连通并且任意一个环的异或和为 000。
在此基础上,求最小生成树。
题目链接:linklinklink
思路
观察题目要求,删增过程中保证图连通且任意一个环的异或和为 000,所以其实 (u,v)(u,v)(u,v) 边的权重是已经确定的,即两点之间边的异或和。
确定完边权后,问题就转换为了对于一个 nnn 个点的完全图,求最小生成树。
为了解决这个问题,我们先了解一下 BoruvkaBoruvkaBoruvka 算法:linklinklink
BoruvkaBoruvkaBoruvka 算法主要针对这些问题:nnn 个点,每个点有点权,任意两个点之间有边权,边权为两个点权用某种计算方式得出,求最小生成树。
对于这些问题,我们通常用 O(log(n))O(log(n))O(log(n)) 的时间找到与点 iii 连边的边权最小的 jjj,具体生成树算法如下:
- 考虑维护当前的连通块(初始每个点为独立的一个连通块)
- 对每个连通块,找到一条与该连通块相连的,且另一端点不在此连通块中的边权最小的边
- 将所有的这些边都加入最小生成树,注意,当加入一条边时需判断该边的两端点是否在同一连通块
- 重复若干遍上述操作,直到图连通
上述算法即为 BoruvkaBoruvkaBoruvka 算法,每次操作完,连通块个数至少减半,则复杂度为 O((n+m)log(n))O((n+m)log(n))O((n+m)log(n))(并查集复杂度为常数)
在本题中,我们可以先以 111 为起点,求出 111 号点到每一个点的异或和 d[i]d[i]d[i],任意两点 u,vu,vu,v 的边权即为 d[u]xord[v]d[u]\ xor\ d[v]d[u] xor d[v]。因此题目转换成,每一个点都有一个权值 d[i]d[i]d[i],任意一条边 (u,v)(u,v)(u,v) 的边权为 d[u]xord[v]d[u] \ xor \ d[v]d[u] xor d[v],求最小生成树。
这个问题即为最小异或生成树问题,可以采用 BoruvkaBoruvkaBoruvka 思想来解决。
首先,由于涉及到了异或,因此引入字典树是非常常见的操作。我们将每一个点的权值从高位到低位依次插入字典树中,然后遍历字典树求答案。对于字典树节点 xxx,当前深度为 stepstepstep,我们令其 000 号儿子为 lxlxlx,111 号儿子为 rxrxrx。
若 lxlxlx 与 rxrxrx 只有一个存在,则一定不存在一条边,其边权中包含 1<<step1<<step1<<step,即继续往下递归即可。
若 lxlxlx 与 rxrxrx 均存在,则一定存在一条边,连接左右两部分,即边权中包含 1<<step1<<step1<<step,因此我们还需要从 lxlxlx 和 rxrxrx 中分别找到一个数字,使其异或值最小。此处可以直接采用贪心的思想,尽可能令每一位的数相同,贪心向下搜索,平均复杂度为 O(log(n))O(log(n))O(log(n)),具体过程见下述代码。
因此本题总复杂度为遍历字典树 +++ 每个节点找最小值,即 O(nlog2(n))O(nlog^2(n))O(nlog2(n))。
代码
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i = a; i <= b; i++)
typedef long long ll;
const int N = 3e6+10;
using namespace std;int n, tot, trie[N][3];
ll d[N];
vector<pair<int, ll> > G[N];void dfs1(int x, int fa) {for(auto it:G[x]) {int y = it.first;ll w = it.second;if(y == fa) continue;d[y] = d[x]^w;dfs1(y,x);}
}void insert(ll w) {int cur = 0;for(int i = 30; i >= 0; i--) {int v = ((w&(1<<i)) > 0);if(!trie[cur][v]) trie[cur][v] = ++tot;cur = trie[cur][v]; }
}ll find(int x, int y, int step) {if(step < 0) return 0;int lx = trie[x][0], rx = trie[x][1];int ly = trie[y][0], ry = trie[y][1];ll minn = 1e15;if(lx) {if(ly) minn = min(minn, find(lx, ly, step-1));else minn = min(minn, find(lx, ry, step-1) + (1<<step));}if(rx) {if(ry) minn = min(minn, find(rx, ry, step-1));else minn = min(minn, find(rx, ly, step-1) + (1<<step));}return minn;
}ll dfs2(int cur, int step) {int ls = trie[cur][0], rs = trie[cur][1];ll ans = 0;if(ls && rs) ans += find(ls, rs, step-1) + (1<<step);if(ls) ans += dfs2(ls, step-1);if(rs) ans += dfs2(rs, step-1);return ans;
}int main()
{scanf("%d",&n);rep(i,1,n-1) {int u,v,w; scanf("%d%d%d",&u,&v,&w);G[u].push_back({v,w});G[v].push_back({u,w});}dfs1(0, -1);rep(i,0,n-1) insert(d[i]);printf("%lld\n", dfs2(0, 30));return 0;
}
【Nowcoder - 5670 B Graph】2020 牛客暑期多校训练营(第五场)【最小异或生成树、Boruvka 思想】相关推荐
- E Groundhog Chasing Death(2020牛客暑期多校训练营(第九场))(思维+费马小定理+质因子分解)
E Groundhog Chasing Death(2020牛客暑期多校训练营(第九场))(思维+费马小定理+质因子分解) 链接:https://ac.nowcoder.com/acm/contest ...
- 2020牛客暑期多校训练营(第一场)
文章目录 A B-Suffix Array B Infinite Tree C Domino D Quadratic Form E Counting Spanning Trees F Infinite ...
- 2020牛客暑期多校训练营(第二场)
2020牛客暑期多校训练营(第二场) 最烦英语题 文章目录 A All with Pairs B Boundary C Cover the Tree D Duration E Exclusive OR ...
- 2020牛客暑期多校训练营(第一场)A B-Suffix Array(后缀数组,思维)
链接:https://ac.nowcoder.com/acm/contest/5666/A 来源:牛客网 题目描述 The BBB-function B(t1t2-tk)=b1b2-bkB(t_1 t ...
- 2020牛客暑期多校训练营(第二场)Just Shuffle
https://ac.nowcoder.com/acm/contest/5667/J 题目大意:给你一个置换A,使得置换P^k=A,让你求出置换P. 思路:我们根据置换A再置换z次,那么就等于置换p ...
- 2020牛客暑期多校训练营(第一场)j-Easy Integration(思维,分数取模,沃斯利积分)
题目链接 题意: 给你一个积分公式,给你一个n,问积分公式的值取模后的结果. 思路: 积分公式(沃利斯积分)值的结论直接就是(n!)^2/(2n+1)!,求个阶乘,再用费马小定理给1/(2n+1)!取 ...
- 2020 牛客暑期多校训练营(第一场)F
题目大意: 多次输入两个a,b字符串他们可以无限次的重复变成aaa,或者bbb 比较他们的大小,相同输出 =,a<b输出 <,a>b输出 >. 输入: aa b zzz zz ...
- 2020牛客暑期多校训练营(第二场)未完待续......
F. Fake Maxpooling 题目: 题目大意: 输入n,m,k.矩阵的尺寸为nm,其中每一个元素为A[i][j] = lcm( i , j ).从中找出所有kk的子矩阵中元素最大的数之和. ...
- 2020牛客暑期多校训练营(第一场)J、Easy Integration (数学、分部积分)
题目链接 题面: 题意: 求给定的定积分. 题解,化成 ∫ xn (1-x)n dx 然后用分部积分法即可得. 分部积分法:∫ udv = uv - ∫ vdu 最终为 n!/((n+1)*(n+2) ...
- 2020牛客暑期多校训练营(第二场)题解
废话 蒟蒻不会积分,K不会做. 文章目录 废话 A. All with Pairs B. Boundary C. Cover the Tree D. Duration E. Exclusive OR ...
最新文章
- python实现三种以上判断条件_Python小课笔记--Python控制流:if逻辑判断
- 如何用PHP写商品折扣_秒杀抢购时的超发,你用php如何优化的
- boost::execution_monitor相关的测试程序
- idea会抛出Unable to import maven project: See logs for details错误
- 牛客网 【每日一题】5月29日 管道取珠
- POJ2083-Fractal【分形,分治】
- 动态规划之91 decode ways
- docker+kafka+zookeeper+zipkin的安装
- 怎样验证软件是否可信?是否被篡改?
- vimpython配色_超漂亮 vim 配置:space-vim
- Java开发笔记(一百三十一)Swing的列表框
- restlet java_restlet(javase版本) 的最基本使用
- excel进销存添加网页模块,可手机开单
- 036--python--摇骰子游戏
- 2018再见|2019你好
- matlab传递函数的分数次方,matlab如何画一个幂函数的曲线?f(x)=(x1)*(x2)^,matlab中如何画出幂函数指数为分数时比如y=x^(1/3...
- Java开发工具排名,你知道几个?
- 拜托,不要再问我Git如何回滚代码
- redis主从架构(上)
- 王道考研数据结构笔记之基本概念
热门文章
- Android工具箱之文件目录
- IIS添加对ashx文件的支持
- C#对IE使用Proxy(代理)
- 成都程序员俱乐部通知
- wordpress文章,页面,小工具如何使用php代码
- STC学习:实时时钟
- 基本系统设备_正规全体灭火系统承包资质品质更好_天霖工程
- directx修复工具 4.0_A12-A13最稳定越狱工具发布,支持iOS13.0—iOS13.3
- cuda10安装_Mmdetection的安装和使用
- 正解mysql: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by /usr/lib64/libstdc++.so.6)