2020牛客暑期多校训练营(第五场)B - Graph (异或 最小生成树 分治 Trie)
B - Graph
- 每次操作不会改变两点之间的路径异或和
- 以 1 号点为起点,算出任意一点到 1 号点的异或值 dis[i](把该值当做 i 号点权值), 那么任意两点的异或值为 \(dis[i]~xor~ dis[j]\),该值也是 i, j两点的边权。
- 计算xor最小生成树即可(模版题),具体来说,将每个点的权值二进制表示后,优先考虑高bit位,分成两组,组内递归解决子问题,组与组之间要找两个异或结果最小的点连边(可以用Trie在O(n*30)实现)。
为什么可以这么做,因为优先考虑了高bit位,比如说我们考虑了第29位,将第29位是1的点分为一组,另外的点分为一组,组与组之间只会连一个边,该边是整个图里面唯一一条含有 \(2^{29}\) 的一条边。如果不这么做,那么一定不止有一条含有\(2^{29}\) 的边。
复杂度\(O(30*n\log n)\),不到1e8
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define dbg(x...) do { cout << "\033[32;1m" << #x <<" -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
const int N = 100000 + 5;
int n, head[N], ver[N<<1], nxt[N<<1], edge[N<<1], tot;
int dis[N], tr[N*30][2], totn;
ll res;
void add(int x, int y, int z){
ver[++tot] = y, edge[tot] = z, nxt[tot] = head[x], head[x] = tot;
}
void dfs(int x, int fa){
for(int i = head[x];i;i=nxt[i]){
int y = ver[i];if(y == fa) continue;
dis[y] = dis[x] ^ edge[i];
dfs(y, x);
}
}
void insert(int x){
int p = 0;
for(int i=29;i>=0;i--){
int c = x >> i & 1;
if(tr[p][c] == 0) tr[p][c] = ++totn;
p = tr[p][c];
}
}
int get(int x) {
int p = 0, res = 0;
for(int i=29;i>=0;i--){
int c = x >> i & 1;
if(tr[p][c]) {
p = tr[p][c];
} else {
res += 1 << i;
p = tr[p][c^1];
}
}
return res;
}
void get(int l, int r, int dep) {
if(dep == -1 || l > r) return;
int R = dis[r] >> dep & 1;
int L = dis[l] >> dep & 1;
if(L == R){ // 整个组按照 dep 位分组,整组一样。
get(l, r, dep - 1);
return;
}
int mid = l;
for(int i=l;i<=r;i++) {
if(dis[i] >> dep & 1) {
mid = i - 1; break;
}
}
// 子问题递归求解
get(l, mid, dep-1);
get(mid+1, r, dep-1);
for(int i=l;i<=mid;i++) {
insert(dis[i]); // 插入字典树
}
int Min = INT_MAX;
for(int i=mid+1;i<=r;i++){
Min = min(Min, get(dis[i]));
}
res += Min;
// 清空
for(int i=0;i<=totn;i++) tr[i][0] = tr[i][1] = 0;
totn = 0;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("i.in","r",stdin);
// freopen("o.out","w",stdout);
#endif
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);
add(y, x, z);
}
dfs(1, 0); // 求出所有点到 1 号点的异或和
sort(dis + 1, dis + 1 + n);
get(1, n, 29);
printf("%lld\n", res);
return 0;
}
2020牛客暑期多校训练营(第五场)B - Graph (异或 最小生成树 分治 Trie)的更多相关文章
- 2020牛客暑期多校训练营(第一场)H Minimum-cost Flow
Minimum-cost Flow 题目:给n个点,m条边.接下来m行包含(a,b,c),即a,b之间有单位流量代价为c的边.接下来有q个问题,每个问题给定(x,y),即假设每条边的容量为x/y时,从 ...
- 2020牛客暑期多校训练营(第二场) Boundary
传送门:Boundary 题意:给你n个点的坐标,问最多有多少个点可以在同一个圆上,(0,0)必须在这个圆上. 题解:三个点确定一个圆,所以暴力枚举两个点和(0,0)组成的圆,如果三个点不共线的话, ...
- 2020牛客暑期多校训练营(第一场)Easy Integration
传送门:J. Easy Integration 题意:给你n,求这个积分,最后的结果分子是记为p,分母记为q. 求(p*q-1)mod 998244353. 题解:比赛完看到巨巨说这是贝塔函数,我一搜 ...
- 2020牛客暑期多校训练营 (第二场) All with Pairs
传送门:All with Pairs 题意:给你n个字符串,求出,f(si,sj)的意思是字符串 si 的前缀和字符串 sj 后缀最长相等部分. 题解:先对所有的字符串后缀hash,用map记录每个h ...
- 2020牛客暑期多校训练营(第二场)Fake Maxpooling
传送门:Fake Maxpooling 题意:给出矩阵的行数n和列数m,矩阵 Aij = lcm( i , j ) ,求每个大小为k*k的子矩阵的最大值的和. 题解:如果暴力求解肯定会t,所以要智取 ...
- 2020牛客暑期多校训练营(第二场) F.Fake Maxpooling (单调队列)
题意:有一个\(n\)x\(m\)的矩阵,\(A_{i,j}=lcm(i,j)\),对于每个\(k\)x\(k\)的子矩阵,其最大元素贡献给答案,求答案的最大值. 题解:矩阵构成我们直接\(i*j/g ...
- 2019牛客暑期多校训练营(第五场) maximum clique 1
题意:给出n个不相同的数,问选出尽量多的数且任两个数字二进制下不同位数大于等于2. 解法:能想到大于等于2反向思考的话,不难发现这是一个二分图,那么根据原图的最大团等于补图的最大独立点集,此问题就变成 ...
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
随机推荐
- Zero date value prohibited解决方法
发现错误 在做新需求时,建了新表,但是在测试debug中,控制台报了java.sql.SQLException: Zero date value prohibited错误 数据库用的是Date类型 实 ...
- 500 份源码合集——GitHub 热点速览 v.21.02
作者:HelloGitHub-小鱼干 GitHub 项目名,如同变量命名,一个好的项目名能让你一眼就知道它是什么.500-AI-Machine-learning-Deep-learning-Compu ...
- 新来的运维这样用HDFS,CIO都懵了···
摘要:本文主要研究了HDFS文件系统的读写流程以及基于MRS在windows客户端下读写HDFS文件的实现. HDFS(Hadoop分布式文件系统)是Apache Hadoop项目的一个子项目. HD ...
- C# 修改PNG图片metadata信息 (含转载fancyblogs博文)
WPF中使用 metadata-extractor可以轻松获取 PNG图片metadata信息 NuGet 获取地址: PM> Install-Package MetadataExtractor ...
- 【转】借助LVS+Keepalived实现负载均衡
一.负载均衡:必不可少的基础手段 1.1 找更多的牛来拉车吧 当前大多数的互联网系统都使用了服务器集群技术,集群即将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是Web应用服务 ...
- HP(惠普)服务器 修复 Intelligent Provisioning(摘录)
摘录自:https://www.xxshell.com/1219.html 我们在给惠普服务器安装操作系统和配置RAID最常用的就是通过F10(Intelligent Provisioning)进行, ...
- Oracle获取session的IP方法
方法1 创建触发器: create orreplace trigger login_on alfterlogon on database begin dbms_application_info ...
- XSS - Pikachu
概述: Cross-Site Scripting 简称为"CSS",为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS.一般XSS可以分为如下几种常见类型 ...
- Java 如何给Word文档添加多行文字水印
前言 我在以往的文章中曾介绍过如何给Word文档添加文本水印和图片水印,及怎样删除文档中的水印.关于文本水印,之前那篇教程里主要指的是单行字体的水印,而在操作Word文档时,有时也会碰到需要添加多行文 ...
- python(re正则)
import re #导入模块 info = 'qwewwer12332423kdsjfkl2342kdjfl213nkafal123123' 例1: res1 = re.compile('er( ...