[题解] LuoguP5666 树的重心
这个题......确实是CSPNOIP题qwq
感觉猜到一个性质就差不多了,首先,对于一棵树,随便拎一个节点\(rt\)当根节点,那么他的重心一定在\(rt\)的重儿子里,进一步的,可以发现重心一定在\(rt\)向下的重链上。
根据这条性质,以及重链上从上到下节点的\(size\)一定是递减的,所以考虑在重链上倍增。
具体的令\(f[x][i]\)表示\(rt\)为根的时候,节点\(x\)沿着重链向下走\(2^i\)步到达的节点,这样,求重心从大到小枚举\(i\),向下跳就好了,另外一些细节可以自己画一个简单的图感性理解一下\(qwq\)。
基于上面的那个求重心的方法,类似换根\(dp\),二次扫描维护\(f\)和重儿子求答案就好了。
实现详见代码(配合c++11食用qaq):
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
typedef vector<int> VI;
const int N=3e5+10,LOGN=20;
VI g[N];
int n,siz[N],f[N][23],son[N],fa[N];
ll ans;
void getf(int x) {
rep(i,1,LOGN) f[x][i]=f[f[x][i-1]][i-1];
}
void calc(int x) {
int u=x;
per(i,0,LOGN) {
if(f[u][i]&&siz[f[u][i]]*2>=siz[x]) // 这里可以画张图感性理解一下qwq
u=f[u][i];
}
if(siz[u]*2==siz[x]) ans+=fa[u];
ans+=u;
}
void dfs(int x,int ff) {
fa[x]=ff;
siz[x]=1,siz[son[x]=0]=0;
for(auto v:g[x]) if(v!=ff) {
dfs(v,x),siz[x]+=siz[v];
if(siz[v]>siz[son[x]]) son[x]=v;
}
f[x][0]=son[x],getf(x);
}
void getans(int x,int ff) {
int x1=0,x2=0; siz[0]=0;
for(auto v:g[x]) { // 枚举与x相邻的点,算出最大的儿子和次大的儿子
if(siz[v]>=siz[x1]) x2=x1,x1=v;
else if(siz[v]>=siz[x2]) x2=v;
}
for(auto v:g[x]) if(v!=ff) {
calc(v);
f[x][0]=v==x1?x2:x1,getf(x); //
siz[x]-=siz[v],siz[v]+=siz[x];
calc(x);
fa[x]=v,getans(v,x);
siz[v]-=siz[x],siz[x]+=siz[v]; // 在算完边(x,v)对答案的贡献的时候要注意撤回影响
}
f[x][0]=son[x]; // 回溯的时候撤销操作
getf(x),fa[x]=ff;
}
void sol() {
memset(siz,0,sizeof(siz));
memset(son,0,sizeof(son));
memset(f,0,sizeof(f));
memset(fa,0,sizeof(fa)); // 多测不清空抱凛两行泪TAT
ans=0; scanf("%d",&n);
rep(i,0,n+1) g[i].clear();
rep(i,0,n-1) {
int x,y; scanf("%d%d",&x,&y);
g[x].pb(y),g[y].pb(x);
}
dfs(1,0),getans(1,0);
printf("%lld\n",ans);
}
int main() {
int _; scanf("%d",&_); while(_--) sol();
return 0;
}
另外,听说NOIP复活了?
[题解] LuoguP5666 树的重心的更多相关文章
- 题解-FJOI2014 树的重心
FJOI2014 树的重心 \(Q\) 组测试数据.给一棵树大小为 \(n\),求有多少个子树与其重心相同.重心可能有多个. 数据范围:\(1\le Q\le 50\),\(1\le n\le 200 ...
- POJ 1655 Balancing Act ( 树的重心板子题,链式前向星建图)
题意: 给你一个由n个节点n-1条边构成的一棵树,你需要输出树的重心是那个节点,以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的 题解: 树的重心定义:找到一个点,其所 ...
- CSP2019 树的重心 题解
本题当然可以通过大力讨论每棵子树的size的大小关系,然后用各种数据结构暴力维护.但是我更倾向于用一种更为性质的做法. 首先讲一下我在考场上想到的做法(没写).就是考虑换根,在换根的过程中计算每一条边 ...
- 【JZOJ6435】【luoguP5666】【CSP-S2019】树的重心
description analysis 需要知道一棵树的重心一定在从根出发的重链上,可以考虑先进行树链剖分弄出重儿子和次重儿子,再倍增维护重儿子 由于重链上有一个或两个重心,接下来求的重心都是深度较 ...
- [CSP-S2019]树的重心 题解
CSP-S2 2019 D2T3 考场上扔了T2来打这题的部分分,然后没看到数据范围是等号,不知道怎么判完全二叉树然后40分滚粗…… ---- 思路分析 很容易想到$O(n^2)$每次暴力找重心,这个 ...
- POJ 1655 求树的重心
POJ 1655 [题目链接]POJ 1655 [题目类型]求树的重心 &题意: 定义平衡数为去掉一个点其最大子树的结点个数,求给定树的最小平衡数和对应要删的点.其实就是求树的重心,找到一个点 ...
- 洛谷P3345 [ZJOI2015]幻想乡战略游戏(动态点分治,树的重心,二分查找,Tarjan-LCA,树上差分)
洛谷题目传送门 动态点分治小白,光是因为思路不清晰就耗费了不知道多少时间去gang这题,所以还是来理理思路吧. 一个树\(T\)里面\(\sum\limits_{v\in T} D_vdist(u,v ...
- 点分治模板(洛谷P4178 Tree)(树分治,树的重心,容斥原理)
推荐YCB的总结 推荐你谷ysn等巨佬的详细题解 大致流程-- dfs求出当前树的重心 对当前树内经过重心的路径统计答案(一条路径由两条由重心到其它点的子路径合并而成) 容斥减去不合法情况(两条子路径 ...
- POJ 1655 - Balancing Act - [DFS][树的重心]
链接:http://poj.org/problem?id=1655 Time Limit: 1000MS Memory Limit: 65536K Description Consider a tre ...
随机推荐
- 从零构建以太坊(Ethereum)智能合约到项目实战——学习笔记10
P57 .1-Solidity Types - 玩转 Solidity 数组 (Arrays) 学习目标 1.掌握Arrays的可变不可变的创建 2.深度理解可变数组和不可变数组之间的区别 3.二维数 ...
- 吴裕雄--天生自然PythonDjangoWeb企业开发:Django文档阅读简介
Django是基于MVC模式的框架,虽然也被称为“MTV”的模式,但是大同小异.对我们来说,需要了解的是无论是MVC模式还是MTV模式,甚至是其他的什么模式,都是为了解耦.把一个软件系统划分为一层一层 ...
- JDBC 存储过程
存储过程 DROP PROCEDURE IF EXISTS `addUser`; CREATE PROCEDURE `addUser` (),in birthday date,in money flo ...
- LeetCode 101.对称二叉树 - JavaScript
题目描述:给定一个二叉树,检查它是否是镜像对称的. 题目分析 下面这种二叉树就是镜像对称的,符合题目要求: 1 / \ 2 2 / \ / \ 3 4 4 3 解法 1:递归检查 根据题目" ...
- h5 穿透滚动
引子 h5 页面有弹窗浮层时,浮层之下若产生了滚动,滑动浮层时会让其产生滚动.这是示例页面,移动端访问如下: Origin My GitHub 原因 找到的信息里面有两种说法: 使用了 -webkit ...
- python 网络爬虫(二)
一.编写第一个网络爬虫 为了抓取网站,我们需要下载含有感兴趣的网页,该过程一般被称为爬取(crawling).爬取一个网站有多种方法,而选择哪种方法更加合适,则取决于目标网站的结构. 首先探讨如何安全 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:强制元素隐藏
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- C语言入门书籍知识点记录
1. 数据在内存中的存储(二进制存储) 内存条:电路的电压有两种状态:0V或者5V,对应的一个元器件有2种状态:0 或者1. 一般情况下我们不一个一个的使用元器件,而是将8个元器件看做一个单位. 一个 ...
- 报错google.protobuf.text_format.ParseError: 166:8 : Message type "object_detection.protos.RandomHorizontalFlip" has no field named "i".解决方法
运行python train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/ssd_mobilenet_ ...
- 4.8.2.JSDOM对象控制HTML元素详解
1 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title ...