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 ...
随机推荐
- 初识vue-简单的自定义标签页面
vue3.0比vue2.0简化了许多. 在这里呢就做了一个简单的标签页面.在这当中难免会有些错误,请勿见怪. 1.vue的页面编写,也就是app.vue这个文件作为主入口文件,当然这个主入口文件也可以 ...
- WebApi 中请求的 JSON 数据字段作为 POST 参数传入
使用 POST 方式请求 JSON 数据到服务器 WebAPI 接口时需要将 JSON 格式封装成数据模型接收参数.即使参数较少,每个接口仍然需要单独创建模型接收.下面方法实现了将 JSON 参数中的 ...
- 关联实现下-jsonpath取值(有难度!!耗时长)
re的使用参考:正则表达式基础及re模块:https://www.cnblogs.com/dream66/p/12953729.html import restr1 = '{"access_ ...
- 原生javascript制作省市区三级联动详细教程
多级联动下拉菜单是前端常见的效果,省市区三级联动又属于其中最典型的案例.多级联动一般都是与数据相关联的,根据数据来生成和修改联动的下拉菜单.完成一个多级联动效果,有助于增强对数据处理的能力. 本实例以 ...
- 【Docker】安装docker18.09.6后,无法启动
------------------------------------------------------------------------------------------------- | ...
- 【Oracle】dump函数用法
Oracle dump函数的用法 一.函数标准格式: DUMP(expr[,return_fmt[,start_position][,length]]) 基本参数时4个,最少可以填的参数是0个.当完全 ...
- C# ADO.NET连接字符串详解
C#中连接字符串包含以下内容 参数 说明 Provider 设置或者返回提供的连接程式的名称,仅用于OLeDbConnection对象 Connection Timeout 在终止尝试并产生异常前,等 ...
- High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载
小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...
- 机器学习基础——规则化(Regularization)
在机器学习中,我们一直期望学习一个泛化能力(generalization)强的函数只有泛化能力强的模型才能很好地适用于整个样本空间,才能在新的样本点上表现良好. \[y=a+bx+cx^2+dx^3\ ...
- 系列trick - bitmask
目录 系列trick - bitmask 拆位 位运算优化(点少的)图操作 位筛 系列trick - bitmask 拆位 主体思想:位之间不影响,把每一位拆开来考虑贡献,转化成非常容易考虑的 0/1 ...