[换根DP][倍增]luogu P5666 树的重心
题面
https://www.luogu.com.cn/problem/P5666
分析
对于一棵以i为根的树来说,它的重心必然在其size大于等于sumsize/2的子树中。
那么断掉一条边e(u,v)时,我们对于断掉边的u,v进行讨论,然后向他们的重儿子倍增直到满足其size≤sumsize/2。
具体实现时可能存在两个重心,所以要判断一下找到的点的重儿子和其父亲。
然后换根的时候维护一下size和father就行了。
代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=3e5+10;
struct Graph {
int v,nx;
}g[2*N];
int cnt,list[N];
int t,n,sz[N],h[2][N],bg[N],d[N][20],f[2][N];
ll ans; void Add(int u,int v) {g[++cnt]=(Graph){v,list[u]};list[u]=cnt;} void DFS1(int u) {
sz[u]=1;h[0][u]=h[1][u]=bg[u]=0;
for (int i=list[u];i;i=g[i].nx)
if (g[i].v!=f[0][u]) {
f[1][g[i].v]=f[0][g[i].v]=u;DFS1(g[i].v);sz[u]+=sz[g[i].v];
if (sz[g[i].v]>sz[h[0][u]]) h[1][u]=h[0][u],bg[u]=h[0][u]=g[i].v;
else if (sz[g[i].v]>sz[h[1][u]]) h[1][u]=g[i].v;
}
d[u][0]=h[0][u];
for (int i=1;i<=18;i++) d[u][i]=d[d[u][i-1]][i-1];
} void DFS2(int u) {
for (int i=list[u],x;i;i=g[i].nx)
if(g[i].v!=f[0][u]) {
sz[u]=n-sz[g[i].v];
if (g[i].v==h[0][u]) bg[u]=h[1][u]; else bg[u]=h[0][u];
if (sz[bg[u]]<sz[f[0][u]]) bg[u]=f[0][u];
f[1][u]=f[1][g[i].v]=0;d[u][0]=bg[u];
for (int j=1;j<=18;j++) d[u][j]=d[d[u][j-1]][j-1];
x=u;
for (int j=18;j>=0;j--) if (sz[d[x][j]]>sz[u]/2) x=d[x][j];
if (max(sz[bg[x]],sz[u]-sz[x])<=sz[u]/2) ans+=x;
if (max(sz[bg[bg[x]]],sz[u]-sz[bg[x]])<=sz[u]/2) ans+=bg[x];
if (max(sz[bg[f[1][x]]],sz[u]-sz[f[1][x]])<=sz[u]/2) ans+=f[1][x];
x=g[i].v;
for (int j=18;j>=0;j--) if (sz[d[x][j]]>sz[g[i].v]/2) x=d[x][j];
if (max(sz[bg[x]],sz[g[i].v]-sz[x])<=sz[g[i].v]/2) ans+=x;
if (max(sz[bg[bg[x]]],sz[g[i].v]-sz[bg[x]])<=sz[g[i].v]/2) ans+=bg[x];
if (max(sz[bg[f[1][x]]],sz[g[i].v]-sz[f[1][x]])<=sz[g[i].v]/2) ans+=f[1][x];
f[1][u]=g[i].v;
DFS2(g[i].v);
}
sz[u]=n-sz[f[1][u]=f[0][u]];d[u][0]=bg[u]=h[0][u];
for (int i=1;i<=18;i++) d[u][i]=d[d[u][i-1]][i-1];
} int main() {
for (scanf("%d",&t);t;t--) {
scanf("%d",&n);memset(list,cnt=0,sizeof list);
for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v),Add(v,u);
ans=0;DFS1(1);DFS2(1);
printf("%lld\n",ans);
}
}
[换根DP][倍增]luogu P5666 树的重心的更多相关文章
- Acesrc and Travel(2019年杭电多校第八场06+HDU6662+换根dp)
题目链接 传送门 题意 两个绝顶聪明的人在树上玩博弈,规则是轮流选择下一个要到达的点,每达到一个点时,先手和后手分别获得\(a_i,b_i\)(到达这个点时两个人都会获得)的权值,已经经过的点无法再次 ...
- [倍增][换根DP]luogu P5024 保卫王国
题面 https://www.luogu.com.cn/problem/P5024 分析 可以对有限制的点对之间的链进行在倍增上的DP数组合并. 需要通过一次正向树形DP和一次换根DP得到g[0][i ...
- [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]
题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...
- 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市
P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...
- P4323-[JSOI2016]独特的树叶【换根dp,树哈希】
正题 题目链接:https://www.luogu.com.cn/problem/P4323 题目大意 给出\(n\)个点的树和加上一个点之后的树(编号打乱). 求多出来的是哪个点(如果有多少个就输出 ...
- 模拟赛:树和森林(lct.cpp) (树形DP,换根DP好题)
题面 题解 先解决第一个子问题吧,它才是难点 Subtask_1 我们可以先用一个简单的树形DP处理出每棵树内部的dis和,记为dp0[i], 然后再用一个换根的树形DP处理出每棵树内点 i 到树内每 ...
- 国家集训队 Crash 的文明世界(第二类斯特林数+换根dp)
题意 题目链接:https://www.luogu.org/problem/P4827 给定一棵 \(n\) 个节点的树和一个常数 \(k\) ,对于树上的每一个节点 \(i\) ,求出 \( ...
- 2018.10.15 NOIP训练 水流成河(换根dp)
传送门 换根dp入门题. 貌似李煜东的书上讲过? 不记得了. 先推出以1为根时的答案. 然后考虑向儿子转移. 我们记f[p]f[p]f[p]表示原树中以ppp为根的子树的答案. g[p]g[p]g[p ...
- 小奇的仓库:换根dp
一道很好的换根dp题.考场上现场yy十分愉快 给定树,求每个点的到其它所有点的距离异或上m之后的值,n=100000,m<=16 只能线性复杂度求解,m又小得奇怪.或者带一个log像kx一样打一 ...
随机推荐
- vue 的 computed 属性在什么时间执行
vue 的 computed 属性在什么时间执行
- NMAP 使用教程!,nmap [Scan Type(s)] [Options] {target specification} , nmap -sn 192.168.2.0/24 , raspberry pi 3
NMAP 使用教程 https://nmap.org/man/zh/man-briefoptions.html 当Nmap不带选项运行时,该选项概要会被输出,最新的版本在这里 http://www.i ...
- how to read the system information by using the node cli tool?
how to read the system information by using the node cli tool? node cli & get system info demos ...
- puppeteer & screenshot
puppeteer & screenshot http://localhost:9812/screenshot?url=https://cdn.xgqfrms.xyz/
- go-admin在线开发平台学习-1[安装、配置、启动]
项目介绍 go-admin 是一个中后台管理系统,基于(gin, gorm, Casbin, Vue, Element UI)实现.主要目的是为了让开发者更专注业务,减少重复代码的编写,节省时间,提升 ...
- linux下安装mysql8.0.x步骤
1.下载mysql mysql官网:https://dev.mysql.com/downloads/mysql/ 将下载的mysql上传打linux 2.解压并重命名 [root@rsyncClien ...
- Redis 使用入门
NoSql概述 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL",它泛指非关系型的数据库, Redis 是一个高性能的开源的.C语言写的Nosql( ...
- docker ssh秘钥免密登录
一.概述 有一台跳板机,已经实现了免密登录后端服务器.但是我写了一个django项目,它是运行在容器中的,也需要免密登录后端服务器. 虽然可以在容器中手动做一下免密登录,但是容器重启之后,之前做的设置 ...
- Python基础语法函数
函数是什么 Python中的函数与数学中的函数不同,它不再只是公式,而是实实在在有着自己特定功能的代码.其实在潜移默化中我们已经有所接触了. 比如print()函数,range()函数,type()函 ...
- 使用 Tye 辅助开发 dotnet 应用程序
newbe.pro 已经给我们写了系列文章介绍Tye 辅助开发k8s 应用: 使用 Tye 辅助开发 k8s 应用竟如此简单(一) 使用 Tye 辅助开发 k8s 应用竟如此简单(二) 使用 Tye ...