description


analysis

  • 需要知道一棵树的重心一定在从根出发的重链上,可以考虑先进行树链剖分弄出重儿子和次重儿子,再倍增维护重儿子

  • 由于重链上有一个或两个重心,接下来求的重心都是深度较大的,只需判断其父节点是否也满足重心的性质即可

  • 现在要断掉一条边\((x,y)\),假设\(x\)是\(y\)的父亲,需要分别求出\(y\)的子树的重心、以及除了\(y\)的子树以外的树的重心

  • 倍增数组已经维护好了所以\(y\)的重心很好求,对于视作\(x\)为根的子树则需要重新维护一次倍增数组

  • 若\(y\)是重儿子则用次重儿子与\(x\)父亲\(size\)比较,否则用原来的重儿子比;知道了重儿子则可以重新算倍增数组

  • 然后把\(x\)设为\(y\)的儿子,其实就是换根操作,递归下去求解,回溯时重新再算\(x\)的倍增数组;时间复杂度\(O(n\log n)\)


code

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define MAXN 300005
#define MAXM MAXN*2
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=las[a];i;i=nex[i]) using namespace std; ll las[MAXM],nex[MAXM],tov[MAXM];
ll fa[MAXN],size[MAXN],tsize[MAXN],hson[MAXN],secson[MAXN];
ll son[MAXN][20];
ll n,T,tot,ans,log2n; inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline ll max(ll x,ll y){return x>y?x:y;}
inline ll min(ll x,ll y){return x<y?x:y;}
inline void link(ll x,ll y){nex[++tot]=las[x],las[x]=tot,tov[tot]=y;} inline void dfs1(ll x,ll y)
{
size[x]=1,fa[x]=y;
rep(i,x)if (tov[i]!=y)
{
dfs1(tov[i],x),size[x]+=size[tov[i]];
if (size[tov[i]]>size[hson[x]])secson[x]=hson[x],hson[x]=tov[i];
else if (size[tov[i]]>size[secson[x]])secson[x]=tov[i];
}
tsize[x]=size[x],son[x][0]=hson[x];
}
inline void dfs2(ll x,ll y)
{
rep(i,x)if (tov[i]!=y)
{
if (tov[i]==hson[x])son[x][0]=secson[x];
else son[x][0]=hson[x];
if (size[y]>size[son[x][0]])son[x][0]=y;
fo(k,1,log2n)son[x][k]=son[son[x][k-1]][k-1]; size[x]=n-tsize[tov[i]],size[tov[i]]=tsize[tov[i]],fa[x]=fa[tov[i]]=0; ll now=x;
fd(k,log2n,0)if (son[now][k] && size[x]-size[son[now][k]]<=size[x]/2)now=son[now][k];
if (max(size[son[now][0]],size[x]-size[now])<=size[x]/2)ans+=now;
if (max(size[son[fa[now]][0]],size[x]-size[fa[now]])<=size[x]/2)ans+=fa[now]; now=tov[i];
fd(k,log2n,0)if (son[now][k] && size[tov[i]]-size[son[now][k]]<=size[tov[i]]/2)now=son[now][k];
if (max(size[son[now][0]],size[tov[i]]-size[now])<=size[tov[i]]/2)ans+=now;
if (max(size[son[fa[now]][0]],size[tov[i]]-size[fa[now]])<=size[tov[i]]/2)ans+=fa[now]; fa[x]=tov[i],dfs2(tov[i],x);
}
fa[x]=y,son[x][0]=hson[x],size[x]=tsize[x];
fo(k,1,log2n)son[x][k]=son[son[x][k-1]][k-1];
}
int main()
{
T=read();
while (T--)
{
memset(las,0,sizeof(las)),memset(nex,0,sizeof(nex));
memset(tov,0,sizeof(tov)),memset(secson,0,sizeof(secson));
memset(fa,0,sizeof(fa)),memset(son,0,sizeof(son)),memset(hson,0,sizeof(hson));
n=read(),log2n=(ll)log2(n),ans=tot=0;
fo(i,1,n-1){ll x=read(),y=read();link(x,y),link(y,x);}
dfs1(1,0);
fo(j,1,log2n)fo(i,1,n)son[i][j]=son[son[i][j-1]][j-1];
dfs2(1,0),printf("%lld\n",ans);
}
return 0;
}

【JZOJ6435】【luoguP5666】【CSP-S2019】树的重心的更多相关文章

  1. 【CSP模拟赛】仔细的检查(树的重心&树hash)

    题目描述 nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上.另一天nodgd更无聊,就又画了一张.  这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点 ...

  2. POJ3107Godfather[树形DP 树的重心]

    Godfather Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6121   Accepted: 2164 Descrip ...

  3. poj1655 树的重心 树形dp

    树的重心定义为:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡. 处理处每个节点的孩子有几个,和树的大小就好了. #include< ...

  4. poj3107 求树的重心(&& poj1655 同样求树的重心)

    题目链接:http://poj.org/problem?id=3107 求树的重心,所谓树的重心就是:在无根树转换为有根树的过程中,去掉根节点之后,剩下的树的最大结点最小,该点即为重心. 剩下的数的 ...

  5. 树形DP求树的重心 --SGU 134

    令一个点的属性值为:去除这个点以及与这个点相连的所有边后得到的连通分量的节点数的最大值. 则树的重心定义为:一个点,这个点的属性值在所有点中是最小的. SGU 134 即要找出所有的重心,并且找出重心 ...

  6. 求树的重心(POJ1655)

    题意:给出一颗n(n<=2000)个结点的树,删除其中的一个结点,会形成一棵树,或者多棵树,定义删除任意一个结点的平衡度为最大的那棵树的结点个数,问删除哪个结点后,可以让平衡度最小,即求树的重心 ...

  7. codeforces 685B Kay and Snowflake 树的重心

    分析:就是找到以每个节点为根节点的树的重心 树的重心可以看这三篇文章: 1:http://wenku.baidu.com/link?url=yc-3QD55hbCaRYEGsF2fPpXYg-iO63 ...

  8. POJ 1655 Balancing Act (求树的重心)

    求树的重心,直接当模板吧.先看POJ题目就知道重心什么意思了... 重心:删除该节点后最大连通块的节点数目最小 #include<cstdio> #include<cstring&g ...

  9. POJ3107--Godfather(树的重心)

    vector建图被卡了..改为链式前向星500ms过的..差了四倍多?... 表示不太会用链表建图啊..自己试着写的,没看模板..嗯..果然错了..落了一句话orz 树的重心就是找到一个树中一个点,其 ...

随机推荐

  1. Python3.5-20190518-廖老师-自我笔记-模块

    在Python中,一个.py文件就称之为一个模块(Module) 可以作为module的文件类型有".py".".pyo".".pyc".& ...

  2. ERROR 2003 (HY000): Can't connect to MySQL server on '129.28.149.240' (111) mysql 无法远程连接

    环境: ubuntu  mysql 一. 查看端口 可以看到mysql监控的是本机Ip root@jiang:/etc/mysql/mysql.conf.d# netstat -apn|grep 33 ...

  3. websocket 中使用Service层的方法

    创建公共Utils 类 ApplicationContextRegister @Component @Lazy(false) public class ApplicationContextRegist ...

  4. MySQL 5.7免安装版设置编码格式、设置root用户密码 远程登录.

    一.设置默认编码格式为utf-8 ... 由于免安装版并没有my.ini的配置文件.需要自行粘贴配置并创建一个my.ini 配置如下: [mysql] # 设置mysql客户端默认字符集 defaul ...

  5. C# Winform版批量压缩图片程序

    需求 上周,领导给我分配了一个需求:服务器上的图片文件非常大,每天要用掉两个G的大小的空间,要做一个自动压缩图片的工具处理这些大图片.领导的思路是这样的: 1)打开一个图片,看它的属性里面象素是多少, ...

  6. 线程同步(基于java)

    java线程 同步与异步 线程池 1)多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,A线程修改了B线 程的处理的数据,而B线程又修改了A线程处理的数理.显然这是由于全局资源造成 ...

  7. (动态改变数据源遇到的问题)sqlserver2012:No Dialect mapping for JDBC type: -9解决方案

    public class MySQLServerDialect extends SQLServerDialect { public MySQLServerDialect() { super(); re ...

  8. 【消息中间件】kafka

    一.kafka整体架构 kafka是一个发布订阅模式的消息队列,生产者和消费者是多对多的关系,将发送者与接收者真正解耦: 生产者将消息发送到broker: 消费者采用拉(pull)模式订阅并消费消息: ...

  9. python运行时禁止生成pyc文件

    方法 在环境变量文件~/.bashrc中添加 export PYTHONDONTWRITEBYTECODE=False source ~/.bashrc加载即可 如何从项目中删除所有.pyc文件 fi ...

  10. Stimulsoft_Report纯代码实现数据绑定

    Stimulsoft_Report纯代码实现数据绑定 根据穿的参数动态绑定显示报表,涉及多表查询. 一.前台代码: [code]  <%@ Page Title="" Lan ...