题面

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);
}
}

最新文章

  1. react+redux教程(五)异步、单一state树结构、componentWillReceiveProps
  2. LOL one Key
  3. Java 调用 C++ (Java 调用 dll)康哥手把手教你
  4. Sprint1(第四天11.17)
  5. log4j常用配置以及日志文件保存位置
  6. list&lt;T&gt; 自定义比较器进行排序
  7. Spring IoC — 基于Java类的配置
  8. mysqldump造成Buffer Pool污染的研究
  9. Spring中注解事务方面的问题
  10. JavaScript最全的10种跨域共享的方法
  11. Java、PHP训练场地选择成都传祺播客
  12. 【java】对象克隆protected Object clone() throws CloneNotSupportedException
  13. 解决unbuntu14.04上的eclipse自动退出的问题
  14. java树形菜单实现
  15. Vue:生命周期
  16. 解决SharePoint 2010拒绝访问爬网内容源错误
  17. POJ 2027 - No Brainer
  18. 接口测试工具-Jmeter使用笔记(一:运行一个HTTP请求)
  19. [OpenCV] Samples 02: Mat - 图像矩阵
  20. C语言中线程和进程的区别

热门文章

  1. macOS &amp; uninstall app
  2. super fast sort algorithm in js
  3. egg.js 如何禁用 sensors data
  4. moment.js 时间格式转换
  5. wxPython 创建基本窗口
  6. babel 常用操作
  7. NGK推出SPC算力币,开启算力新玩法!
  8. [转]什么是 C 和 C ++ 标准库?
  9. Iterable object of JavaScript
  10. Vue为何采用异步渲染