题面

https://www.luogu.com.cn/problem/P5666

分析

对于一棵以i为根的树来说,它的重心必然在其size大于等于sumsize/2的子树中。

那么断掉一条边e(u,v)时,我们对于断掉边的u,v进行讨论,然后向他们的重儿子倍增直到满足其size≤sumsize/2。

具体实现时可能存在两个重心,所以要判断一下找到的点的重儿子和其父亲。

然后换根的时候维护一下size和father就行了。

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N=3e5+10;
  7. struct Graph {
  8. int v,nx;
  9. }g[2*N];
  10. int cnt,list[N];
  11. int t,n,sz[N],h[2][N],bg[N],d[N][20],f[2][N];
  12. ll ans;
  13.  
  14. void Add(int u,int v) {g[++cnt]=(Graph){v,list[u]};list[u]=cnt;}
  15.  
  16. void DFS1(int u) {
  17. sz[u]=1;h[0][u]=h[1][u]=bg[u]=0;
  18. for (int i=list[u];i;i=g[i].nx)
  19. if (g[i].v!=f[0][u]) {
  20. f[1][g[i].v]=f[0][g[i].v]=u;DFS1(g[i].v);sz[u]+=sz[g[i].v];
  21. if (sz[g[i].v]>sz[h[0][u]]) h[1][u]=h[0][u],bg[u]=h[0][u]=g[i].v;
  22. else if (sz[g[i].v]>sz[h[1][u]]) h[1][u]=g[i].v;
  23. }
  24. d[u][0]=h[0][u];
  25. for (int i=1;i<=18;i++) d[u][i]=d[d[u][i-1]][i-1];
  26. }
  27.  
  28. void DFS2(int u) {
  29. for (int i=list[u],x;i;i=g[i].nx)
  30. if(g[i].v!=f[0][u]) {
  31. sz[u]=n-sz[g[i].v];
  32. if (g[i].v==h[0][u]) bg[u]=h[1][u]; else bg[u]=h[0][u];
  33. if (sz[bg[u]]<sz[f[0][u]]) bg[u]=f[0][u];
  34. f[1][u]=f[1][g[i].v]=0;d[u][0]=bg[u];
  35. for (int j=1;j<=18;j++) d[u][j]=d[d[u][j-1]][j-1];
  36. x=u;
  37. for (int j=18;j>=0;j--) if (sz[d[x][j]]>sz[u]/2) x=d[x][j];
  38. if (max(sz[bg[x]],sz[u]-sz[x])<=sz[u]/2) ans+=x;
  39. if (max(sz[bg[bg[x]]],sz[u]-sz[bg[x]])<=sz[u]/2) ans+=bg[x];
  40. if (max(sz[bg[f[1][x]]],sz[u]-sz[f[1][x]])<=sz[u]/2) ans+=f[1][x];
  41. x=g[i].v;
  42. for (int j=18;j>=0;j--) if (sz[d[x][j]]>sz[g[i].v]/2) x=d[x][j];
  43. if (max(sz[bg[x]],sz[g[i].v]-sz[x])<=sz[g[i].v]/2) ans+=x;
  44. if (max(sz[bg[bg[x]]],sz[g[i].v]-sz[bg[x]])<=sz[g[i].v]/2) ans+=bg[x];
  45. if (max(sz[bg[f[1][x]]],sz[g[i].v]-sz[f[1][x]])<=sz[g[i].v]/2) ans+=f[1][x];
  46. f[1][u]=g[i].v;
  47. DFS2(g[i].v);
  48. }
  49. sz[u]=n-sz[f[1][u]=f[0][u]];d[u][0]=bg[u]=h[0][u];
  50. for (int i=1;i<=18;i++) d[u][i]=d[d[u][i-1]][i-1];
  51. }
  52.  
  53. int main() {
  54. for (scanf("%d",&t);t;t--) {
  55. scanf("%d",&n);memset(list,cnt=0,sizeof list);
  56. for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v),Add(v,u);
  57. ans=0;DFS1(1);DFS2(1);
  58. printf("%lld\n",ans);
  59. }
  60. }

[换根DP][倍增]luogu P5666 树的重心的更多相关文章

  1. Acesrc and Travel(2019年杭电多校第八场06+HDU6662+换根dp)

    题目链接 传送门 题意 两个绝顶聪明的人在树上玩博弈,规则是轮流选择下一个要到达的点,每达到一个点时,先手和后手分别获得\(a_i,b_i\)(到达这个点时两个人都会获得)的权值,已经经过的点无法再次 ...

  2. [倍增][换根DP]luogu P5024 保卫王国

    题面 https://www.luogu.com.cn/problem/P5024 分析 可以对有限制的点对之间的链进行在倍增上的DP数组合并. 需要通过一次正向树形DP和一次换根DP得到g[0][i ...

  3. [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]

    题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...

  4. 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市

    P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...

  5. P4323-[JSOI2016]独特的树叶【换根dp,树哈希】

    正题 题目链接:https://www.luogu.com.cn/problem/P4323 题目大意 给出\(n\)个点的树和加上一个点之后的树(编号打乱). 求多出来的是哪个点(如果有多少个就输出 ...

  6. 模拟赛:树和森林(lct.cpp) (树形DP,换根DP好题)

    题面 题解 先解决第一个子问题吧,它才是难点 Subtask_1 我们可以先用一个简单的树形DP处理出每棵树内部的dis和,记为dp0[i], 然后再用一个换根的树形DP处理出每棵树内点 i 到树内每 ...

  7. 国家集训队 Crash 的文明世界(第二类斯特林数+换根dp)

    题意 ​ 题目链接:https://www.luogu.org/problem/P4827 ​ 给定一棵 \(n\) 个节点的树和一个常数 \(k\) ,对于树上的每一个节点 \(i\) ,求出 \( ...

  8. 2018.10.15 NOIP训练 水流成河(换根dp)

    传送门 换根dp入门题. 貌似李煜东的书上讲过? 不记得了. 先推出以1为根时的答案. 然后考虑向儿子转移. 我们记f[p]f[p]f[p]表示原树中以ppp为根的子树的答案. g[p]g[p]g[p ...

  9. 小奇的仓库:换根dp

    一道很好的换根dp题.考场上现场yy十分愉快 给定树,求每个点的到其它所有点的距离异或上m之后的值,n=100000,m<=16 只能线性复杂度求解,m又小得奇怪.或者带一个log像kx一样打一 ...

随机推荐

  1. git push bug

    git push bug fast-forwards $ git push $ git push --help # git pull $ gp To http://git.xgqfrms.xyz:88 ...

  2. bob and brad physical therapy knee exercise

    bob and brad physical therapy knee exercise 鲍勃和布拉德物理治疗膝关节运动 https://bobandbrad.com/ youtube https:// ...

  3. macOS & uninstall app

    macOS & uninstall app https://support.apple.com/en-hk/guide/mac-help/install-and-uninstall-other ...

  4. 对DevOps的九大误解,是时候纠正了!

    DevOps是开发和运维的结合,有助于集成和自动化测试过程以及部署存储库,还提供了透明度以及灵活性.DevOps的目标如下: ●更快的上市时间(TTM). ●减少各种修复之间的前置时间.●提高部署频率 ...

  5. ASP.NET Core中如何对不同类型的用户进行区别限流

    老板提出了一个新需求,从某某天起,免费用户每天只能查询100次,收费用户100W次. 这是一个限流问题,聪明的你也一定想到了如何去做:记录用户每一天的查询次数,然后根据当前用户的类型使用不同的数字做比 ...

  6. mysql事务的实现原理

    此篇文章算是对mysql事务的一个总结,基本把mysql事务相关的知识点都涵盖到了,面试问来问去无非也就是这些,在了解这些之前我们先对mysql在执行的过程中 有一个整体的认识,如下图 如上图所示,M ...

  7. 2021年-在windwos下如何用TOMACT发布一个系统(完整配置案列)

    2021年新年第一篇:博主@李宗盛-关于在Windwos下使用TOMCAT发布一个系统的完成配置案列. 之前写过关于TOMCAT的小篇幅文档,比较分散,可以作为对照与参考. 此篇整合在一起,一篇文档写 ...

  8. HTML认知

    <!DOCTYPE html>的作用 1.定义 DOCTYPE是一种标准通用标记语言的文档类型的声明,目的是告诉标准通用标记语言解析器,该用什么方式解析这个文档. <!DOCTYPE ...

  9. Java基础语法:注释

    书写注释是一个非常好的习惯. 注释并不会被执行,是给我们写代码的人看的. Java中的注释有三种: 单行注释(Line comment) 多行注释(Block comment) 文档注释(JavaDo ...

  10. 微信小程序弹出框滚动穿透问题

    1.在你的遮罩层最外层加 catchtouchmove="noneEnoughPeople" 里面是你的方法名2.noneEnoughPeople: function () { c ...