B - Graph

题目链接

  1. 每次操作不会改变两点之间的路径异或和
  2. 以 1 号点为起点,算出任意一点到 1 号点的异或值 dis[i](把该值当做 i 号点权值), 那么任意两点的异或值为 \(dis[i]~xor~ dis[j]\),该值也是 i, j两点的边权。
  3. 计算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)的更多相关文章

  1. 2020牛客暑期多校训练营(第一场)H Minimum-cost Flow

    Minimum-cost Flow 题目:给n个点,m条边.接下来m行包含(a,b,c),即a,b之间有单位流量代价为c的边.接下来有q个问题,每个问题给定(x,y),即假设每条边的容量为x/y时,从 ...

  2. 2020牛客暑期多校训练营(第二场) Boundary

    传送门:Boundary  题意:给你n个点的坐标,问最多有多少个点可以在同一个圆上,(0,0)必须在这个圆上. 题解:三个点确定一个圆,所以暴力枚举两个点和(0,0)组成的圆,如果三个点不共线的话, ...

  3. 2020牛客暑期多校训练营(第一场)Easy Integration

    传送门:J. Easy Integration 题意:给你n,求这个积分,最后的结果分子是记为p,分母记为q. 求(p*q-1)mod 998244353. 题解:比赛完看到巨巨说这是贝塔函数,我一搜 ...

  4. 2020牛客暑期多校训练营 (第二场) All with Pairs

    传送门:All with Pairs 题意:给你n个字符串,求出,f(si,sj)的意思是字符串 si 的前缀和字符串 sj 后缀最长相等部分. 题解:先对所有的字符串后缀hash,用map记录每个h ...

  5. 2020牛客暑期多校训练营(第二场)Fake Maxpooling

    传送门:Fake Maxpooling 题意:给出矩阵的行数n和列数m,矩阵 Aij = lcm( i , j )  ,求每个大小为k*k的子矩阵的最大值的和. 题解:如果暴力求解肯定会t,所以要智取 ...

  6. 2020牛客暑期多校训练营(第二场) F.Fake Maxpooling (单调队列)

    题意:有一个\(n\)x\(m\)的矩阵,\(A_{i,j}=lcm(i,j)\),对于每个\(k\)x\(k\)的子矩阵,其最大元素贡献给答案,求答案的最大值. 题解:矩阵构成我们直接\(i*j/g ...

  7. 2019牛客暑期多校训练营(第五场) maximum clique 1

    题意:给出n个不相同的数,问选出尽量多的数且任两个数字二进制下不同位数大于等于2. 解法:能想到大于等于2反向思考的话,不难发现这是一个二分图,那么根据原图的最大团等于补图的最大独立点集,此问题就变成 ...

  8. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  9. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  10. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

随机推荐

  1. Spring Cloud Gateway 跨域 CORS 配置方式实现

    网上找了一堆文章全是说这样写无效 globalcors: cors-configurations: '[/**]': allowCredentials: true allowedOriginPatte ...

  2. js 判断用户是手机端还是电脑端访问

    通过userAgent 判断,网页可以直接使用 navigation对象 node端 可以通过请求头的 ctx.request.header['user-agent'] const browser = ...

  3. SQL中的主键,候选键,外键,主码,外码

    1.码=超键:能够唯一标识一条记录的属性或属性集. 标识性:一个数据表的所有记录都具有不同的超键 非空性:不能为空 有些时候也把码称作"键" 2.候选键=候选码:能够唯一标识一条记 ...

  4. git revert 回退已经push的内容

    如题,在日常的开发过程中,可能有组员不小心一下子吧文件修改,需要进行回退 回退主要涉及到2种命令,一种是git reset 一种是 git revert git reset 会修改git log提交历 ...

  5. MySQL全面瓦解16:存储过程相关

    概述 大多数SQL语句都是针对一个或多个表的单条语句.但并非所有业务都这么简单,经常会有复杂的操作需要多条语句才能完成. 比如用户购买一个商品,要删减库存表,要生成订单数据,要保存支付信息等等,他是一 ...

  6. 【Java】Java注释 - 单行、块、文档注释

    简单记录,Java 核心技术卷I 基础知识(原书第10 版) 注释 我们在编写程序时,经常需要添加一些注释,用来描述某段代码的作用,提高Java源程序代码的可读性,使得Java程序条理清晰. 写代码的 ...

  7. leetcode 886. 可能的二分法(DFS,染色,种类并查集)

    题目链接 886. 可能的二分法 题意: 给定一组 N 人(编号为 1, 2, ..., N), 我们想把每个人分进任意大小的两组. 每个人都可能不喜欢其他人,那么他们不应该属于同一组. 形式上,如果 ...

  8. CTFHub - Web(二)

    目录遍历: 法一: 依次查看目录即可: 法二: 利用脚本:  #!/usr/bin/python3  # -*- coding: utf-8 -*-  # --author:valecalida-- ...

  9. linux系统中set、env、export关系

    set 用来显示shell变量(包括环境变量.用户变量和函数名及其定义),同时可以设置shell选项来开启调试.变量扩展.路径扩展等开关env 用来显示和设置环境变量export 用来显示和设置导出到 ...

  10. 关于安装版JDK1.8 1.7更改多个JDK环境变量 不生效

    配置maven(apache-maven-3.3.9)时提示异常:'mvn' 不是内部或外部命令,上网查找得知 它不支持jdk1.8,所以重新安装jdk1.7,后来就出现下面的问题 现象: 当使用安装 ...