记录这辈子见到的第一道从上到下的树上倍增

这道题先是浪费我半个下午做,做不出来有时好久看题解实现,气死我了。

题意。

给定一张 \(N\) 点的树,让我们考虑断掉每一条边,统计分裂出的两个子树的重心编号和之和。

要求 \(O(nlogn)\) 或更优的时间复杂度。

做法

这个咋做呢?我们可以在 OIwiki 中发现一些关于树的重心的神秘性质。

我这里粘贴 OIwiki 原文了。

  • 一棵有根树的重心一定在根结点所在的重链上。一棵树的重心一定是该树根结点重子结点对应子树的重心的祖先。

这就非常的贴心了。

我们发现我们很好判断了,若想知道一个点是不是重心,我们仅仅需要判断它的重儿子和除它子树以外的那一部分就行了。

既然判断非常简单了,我们就可以倍增来找了。

有多个怎么办?重心有多个的话两个必然是相邻的,再加一个判断就行了。

为了方便我们就从上往下倍增了,这样我们往重儿子走处理起来会很方便。

至于断边的影响,我们可以单独处理考上断边的倍增数组,把直接的下一个改成次重儿子不就行了。

这个样子就好做多了,我们在 dfs 的时候就可以把每一条边搞定。

代码如下↓

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MN=4e6+315;
int T, n, totsize;
struct Node{int nxt, to;
}node[MN];
int head[MN], tottt;
void insert(int u, int v){node[++tottt].to=v;node[tottt].nxt=head[u];head[u]=tottt; return;
}
int jump[MN][21], fa[MN];
int siz[MN], tmpsiz[MN];
int secw[MN], ans=0;
void init(){for(int i=1; i<=n; ++i){head[i]=secw[i]=siz[i]=tmpsiz[i]=fa[i]=0;for(int j=0; j<=20; ++j) jump[i][j]=0;	}
}
void Pre(){for(int j=1; j<=20; ++j){for(int i=1; i<=n; ++i){if(jump[i][j-1]) jump[i][j]=jump[jump[i][j-1]][j-1];}}
}
void update(int u){for(int j=1; j<=20; ++j){if(jump[u][j-1])jump[u][j]=jump[jump[u][j-1]][j-1];else jump[u][j]=0;}
}
int query(int u, int rt){for(int i=20; i>=0; --i){if(jump[u][i]&&siz[rt]-siz[jump[u][i]]<=siz[rt]/2){u=jump[u][i];}}return u;
}
bool check(int u, int tot){return max(siz[jump[u][0]],tot-siz[u])<=tot/2;
}
void dfs1(int u, int father){tmpsiz[u]=1; fa[u]=father;for(int i=head[u];i;i=node[i].nxt){int v=node[i].to;if(v==father) continue;dfs1(v,u); tmpsiz[u]+=tmpsiz[v];if(tmpsiz[v]>tmpsiz[jump[u][0]]){secw[u]=jump[u][0];jump[u][0]=v;}else if(tmpsiz[v]>tmpsiz[secw[u]]){secw[u]=v;}}siz[u]=tmpsiz[u];
}
void dfs2(int u, int father){int now, sav=jump[u][0];for(int i=head[u];i;i=node[i].nxt){int v=node[i].to;if(v==father) continue;if(v==sav) jump[u][0]=secw[u];else jump[u][0]=sav;if(siz[father]>siz[jump[u][0]]) jump[u][0]=father;update(u); now=u;siz[u]=totsize-tmpsiz[v];siz[v]=tmpsiz[v];fa[u]=fa[v]=0;now=query(u,u);ans+=check(now,siz[u])*now+check(fa[now],siz[u])*fa[now];now=v; now=query(v,v);ans+=check(now,siz[v])*now+check(fa[now],siz[v])*fa[now];fa[u]=v; dfs2(v,u);}jump[u][0]=sav; siz[u]=tmpsiz[u];fa[u]=father; update(u);
}
signed main(){ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin>>T; while(T--){init(); cin>>n;for(int i=1,u,v; i<n; ++i){cin>>u>>v; insert(u,v); insert(v,u);}ans=0; dfs1(1,0); Pre();totsize=siz[1]; dfs2(1,0);cout<<ans<<'\n';}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/919805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

忘形篇

忘形篇先想想暴力怎么做

06.容器存储 - 教程

06.容器存储 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "C…

fm网站开发有源码怎么搭建网站

文章来源&#xff1a;http://blog.csdn.net/edeed/archive/2006/02/10/596271.aspx 1、安装PD v11.0版 2、由pdm生成建表脚本时&#xff0c;字段超过15字符就发生错误&#xff08;oracle&#xff09; 原因未知&#xff0c;解决办法是打开PDM后&#xff0c;会出现Database的菜单…

电子商务网站如何进行维护和推广建设部网站官网挂证通报

ARM32位系统的内存布局图 32位操作系统的内存布局很经典&#xff0c;很多书籍都是以32位系统为例子去讲解的。32位的系统可访问的地址空间为4GB&#xff0c;用户空间为1GB ~ 3GB&#xff0c;内核空间为3GB ~ 4GB。 为什么要划分为用户空间和内核空间呢&#xff1f; 一般处理器…

一般路人向第39次CSP认证

一般路人向第39次CSP认证Q1 第一题十分水,照着他意思来就行了,十来分钟写出来交上去,不行。反复确认直到半个小时,发现交到第二题上去了。 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int m, n; do…

1748:约瑟夫问题

题目 总时间限制: 1000ms 内存限制: 65536kB 描述 约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样…

做报名统计的网站微门户网站建设

前面两篇文章记录了 Spring IOC 的相关知识&#xff0c;本文记录 Spring 中的另一特性 AOP 相关知识。 部分参考资料&#xff1a; 《Spring实战&#xff08;第4版&#xff09;》 《轻量级 JavaEE 企业应用实战&#xff08;第四版&#xff09;》 Spring 官方文档 W3CSchool Spri…

net网站开发教程简易微网站模板

构造器最大的作用:创建对象. 为什么使用反射创建对象,为什么不直接来new呢? 在框架中,提供给我们的都是字符串. ----------------------------------------------------------- 使用反射创建对象: 步骤: 1);找到构造器所在类的字节码对象. 2):获取构造器对象. 3):使用反射…

安全可信网站营销活动策划方案模板

前言 Python可以用于复杂的数据分析和Web开发项目&#xff0c;还能以极少的代码行数完成令人惊叹的任务。本文将分享25个简短的Python代码示例&#xff0c;用来展示Python编程语言的魅力和效率。 1.列表推导式 Python的列表推导式提供了一种优雅的方法来创建列表。 # 将一个…

完整教程:微论-神经网络的亲情密码,权重矩阵的家庭关系论

完整教程:微论-神经网络的亲情密码,权重矩阵的家庭关系论2025-09-27 18:26 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !importan…

Ansible + Docker 部署 Apache Nifi 1.28 单用户集群

Ansible + Docker 部署 Apache Nifi 1.28 单用户集群1. 准备工作 1.1 主机列表IP 主机名 内存(GB) CPU核数 磁盘 操作系统 CPU 架构10.0.0.13 arc-pro-dc01my.registry.com 16 1 500GB CentOS 7.9.2009 x86_6410.0.…

候机的队伍

候机的队伍今天乘机,小朋友们很激动地早早地去排队了。我苦口婆心地教育他们,不需要这么早排队。因为座位都是固定的,而需要早排队的理由只有两个: 1. 带了较多行李,需要早点登机占个位置。 2. 缓解焦虑,早点坐上…

个人网站怎么做支付功能抖音代运营合作协议免费

聚苯乙烯&#xff08;Polystyrene&#xff0c;简称PS&#xff09;是一种常见的合成聚合物&#xff0c;属于热塑性塑料。它是由苯乙烯单体聚合而成的&#xff0c;具有轻质、透明或半透明、电绝缘性好等特点。常见: 包装材料白色泡沫塑料&#xff08;EPS&#xff0c;用于包装、保…

网站推广策划的思路包括哪些内容广州网站建设功能

来源&#xff1a;半导体行业观察摘 要在本项目中&#xff0c;我们提出了一种基于学习的芯片布局方法&#xff0c;这是芯片设计过程中最复杂&#xff0c;最耗时的阶段之一。与以前的方法不同&#xff0c;我们的方法具有从过去的经验中学习并随着时间的推移而不断改进的能力。特别…

Keil uVision5 设置 hex 输出路径,不放Objects目录下

前言全局说明最近从 keil 2 换到 keil5, 新建项目后编译输出的 .hex 文件被放到 Objects目录下,找着不方便。一、说明 1.1 环境: Windows 7 旗舰版二、修改路径 2.1 打开项目设置选项 从工具栏打开或 从菜单里打开2.…

深入解析:【Linux】进程概念(六):进程地址空间深度解析:虚拟地址与内存管理的奥秘

深入解析:【Linux】进程概念(六):进程地址空间深度解析:虚拟地址与内存管理的奥秘pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; f…

深入解析:Metal - 5.深入剖析 3D 变换

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

垃圾收集器G1ZGC详解

垃圾收集器G1&ZGC详解 一、G1 收集器(-XX:+UseG1GC) G1(Garbage-First)是面向多处理器、大内存的服务器级收集器,核心目标是可预测的 GC 停顿时间与高吞吐量平衡。1. 核心特性Region 划分:将 Java 堆划分为最…

菠菜网站怎么做外贸网站该怎么做

控制actor在level中沿着一个spline path运动。 由finterp to 函数的输出数值来控制每一帧actor运动的距离。 从开始位置到spline path的终点的时间&#xff0c;是1/interp speed。假如我们控制actor从开头到终点运动的总时间是1秒&#xff0c;那么 interp speed就传入0.5&#…

Godot Outline

Godot OutlineGodot 4.5 这几天更新了,补全了模板缓冲, 在渲染Depth Buffer时,一般使用D32S8的类似格式。在Godot中,原本Depth Buffer就只渲染了Depth,因此S8的通道没有被使用。Stencil即特定材质可以向这个通道里…