题目

一棵树的重心定义为一个点满足删除这个点后最大的连通块大小小于等于原来这颗树大小的一半。

给出一棵树,一次操作为删除一条边再添加一条边,操作结束后必须仍为一棵树。问这颗树的每个点是否可以通过一次操作使它变成新树的重心。

\(n\le 4\times 10^5\)。

分析

如果一个点原来不是重心,那么这个点必定只有一个子树的大小大于\(\frac{n}{2}\) 。要让这个点变成重心,那么需要在这个子树中切出尽量大的一块,使它的大小小于等于\(\frac{n}{2}\) 。如果这颗子树中剩下的大小也小于等于\(\frac{n}{2}\) ,那么就可以,否则一定不行。

于是问题就变成了求对于每个点,以它为根的子树中最大能切出一个多大的子树,大小小于等于 \(\frac{n}{2}\) ;除去这个点的子树剩下的树中最大能切出多大的子树,大小小于等于\(\frac{n}{2}\) (即上面的那颗“子树”)。

这可以通过两次dfs(树形dp)得到,一次求\(\text{down[x]}\),一次用\(\text{down}\)的信息求出\(\text{up[x]}\) 。一个点的\(\text{up}\)有可能是父亲的\(\text{up}\) ,也有可能是切掉它连去父亲的那条边得到的子树大小,也可能是父亲的另一颗子树的\(\text{down}\)。

这题的关键其实在于想到**在这个子树中切出尽量大的一块,使它的大小小于等于\(\frac{n}{2}\) ** ,而不是找其中重心之类思路。

代码

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=4e5+1;
int n,hf,size[maxn],up[maxn],down[maxn],which[maxn],msize[maxn];
bool ans[maxn];
vector<int> g[maxn];
void add(int x,int y) {g[x].push_back(y);}
int Size(int x,int fa) {
int &sz=size[x]=1,&ms=msize[x]=0;
for (int v:g[x]) if (v!=fa) {
int ret=Size(v,x);
sz+=ret,ms=max(ms,ret);
}
ms=max(ms,n-size[x]);
return sz;
}
void Root(int x,int fa) {
for (int v:g[x]) if (v!=fa && size[v]>=hf) which[x]=v,Root(v,x);
}
void Down(int x,int fa) {
for (int v:g[x]) if (v!=fa) Down(v,x),down[x]=max(down[x],down[v]);
if (size[x]<=hf) down[x]=size[x];
}
void Up(int x,int fa) {
pair<int,int> fir(0,0),sec(0,0);
for (int v:g[x]) if (v!=fa) if (down[v]>fir.first) swap(fir,sec),fir=make_pair(down[v],v); else if (down[v]>sec.first) sec=make_pair(down[v],v);
for (int v:g[x]) if (v!=fa) {
int &nxt=up[v]=max(up[x],v==fir.second?sec.first:fir.first);
if (n-size[v]<=hf) nxt=max(nxt,n-size[v]);
Up(v,x);
}
}
void dfs(int x,int fa) {
if (msize[x]<=hf) ans[x]=true; else {
if (which[x]>0) ans[x]=(size[which[x]]-down[which[x]]<=hf); else
ans[x]=(n-size[x]-up[x]<=hf);
}
for (int v:g[x]) if (v!=fa) dfs(v,x);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
hf=(n=read())>>1;
for (int i=1;i<n;++i) {
int x=read(),y=read();
add(x,y),add(y,x);
}
Size(1,1),Root(1,1);
Down(1,1);
Up(1,1);
dfs(1,0);
for (int i=1;i<=n;++i) putchar("01"[ans[i]]),putchar(" \n"[i==n]);
return 0;
}

CF708C-Centroids的更多相关文章

  1. CF708C Centroids(树形DP)

    发现变重心就是往重心上割,所以\(\text{up and down}\),一遍统计子树最大\(size\),一遍最优割子树,\(down\),\(up\)出信息,最后\(DFS\)出可行解 #inc ...

  2. codeforces708C

    CF708C Centroids 题意翻译 给定一颗树,你有一次将树改造的机会,改造的意思是删去一条边,再加入一条边,保证改造后还是一棵树. 请问有多少点可以通过改造,成为这颗树的中心?(如果以某个点 ...

  3. codeforces 709E E. Centroids(树形dp)

    题目链接: E. Centroids time limit per test 4 seconds memory limit per test 512 megabytes input standard ...

  4. 【CodeForces】708 C. Centroids 树的重心

    [题目]C. Centroids [题意]给定一棵树,求每个点能否通过 [ 移动一条边使之仍为树 ] 这一操作成为树的重心.n<=4*10^5. [算法]树的重心 [题解]若树存在双重心,则对于 ...

  5. Codeforces Round #670 (Div. 2) C. Link Cut Centroids (dfs,树)

    C. Link Cut Centroids Fishing Prince loves trees, and he especially loves trees with only one centro ...

  6. (ICONIP2021)On the Unreasonable Effectiveness of Centroids in Image

    目录 摘要 1.引言 2.提出的方法 2.1 CentroidTripletloss 2.2 聚合表示 3.实验 3.1 数据集 3.2 应用细节 3.3 Fashion检索结果 3.4 行人再识别结 ...

  7. Codeforces708C Centroids 【树形dp】

    题目链接 题意:给定一棵n个结点的树,问:对于每个结点,能否通过删除一条边并添加一条边使得仍是树,并且删除该结点后得到的各个连通分量结点数 <= n/2? 题解:树形dp,两遍dfs,第一遍df ...

  8. Codeforces 709E. Centroids 树形DP

    题目链接:http://codeforces.com/contest/709/problem/E 题意: 给你一棵树,你可以任删一条边和加一条边,只要使得其仍然是一棵树,输出每个点是否都能成为重心 题 ...

  9. CF708C题解

    挺简单的一道数据结构... 首先考虑这个"改造"的本质,很明显是把一颗子树塞到了另一个节点下面. 考虑一个节点可能成为重心的条件.条件很明显是只有一颗子树的大小大于 \(\frac ...

  10. Centroids (换根DP)

    题面 题解 删一条边.加一条边,相当于把一个子树折下来,然后嫁接在一个点上, 那么最优的情况肯定是接在根上,对吧,很好理解吧 那么这个拆下来的子树大小就不能超过n/2. 我们用son[]来表示每个点为 ...

随机推荐

  1. 20155305 2016-2017-2 《Java程序设计》实验三 敏捷开发与XP实践

    20155305 2016-2017-2 <Java程序设计>实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 1.敏捷开发 敏捷开发 ...

  2. 20145209刘一阳《网络对抗》Exp9 Web安全基础实践

    20145209刘一阳<网络对抗>Exp9 Web安全基础实践 基础问题回答 1.SQL注入攻击原理,如何防御? SQL注入攻击就是通过把SQL命令插入到Web表单递交或输入域名或页面请求 ...

  3. 20145226夏艺华 网络对抗技术EXP4 恶意代码分析

    20145226夏艺华 网络对抗技术EXP4 恶意代码分析(未完成版) 回答问题 (1)如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作 ...

  4. 21045234黄斐《java程序设计》第四周

    教材学习内容总结 第六章部分 - 继承与多态 何谓继承 继承面向对象中,子类继承父类,避免重复的行为定义.一般来说,父类的父类也称父类,且同一个子类只允许拥有一个父类,而同一个父类则可以拥有多个子类. ...

  5. BZOJ1096_仓库建设_KEY

    题目传送门 一道斜率优化的题目,加深了印象. 设sum[i]=∑p[i],S[i]=∑p[i]*x[i]. 暴力方程加前缀和优化: f[i]=min(f[j]+c[i]+(sum[i]-sum[j]) ...

  6. PostgreSQL参数学习:wal_keep_segments

    http://www.postgresql.org/docs/9.3/static/runtime-config-replication.html 参考官方文档: wal_keep_segments ...

  7. 【LG3233】[HNOI2014]世界树

    题面 洛谷 题解 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include < ...

  8. 半个小时教你写一个装(bi)逼(she)之地图搜租房

    半个小时教你写一个装(bi)逼(she)之地图搜租房 首先需要一个Python3环境,怎么准备我就不多说了,实在不会的出门右转看一下廖雪峰老师的博客. HTML部分 代码来自:高德API+Python ...

  9. cogs62 [HNOI2004] 宠物收养所

    cogs62 [HNOI2004] 宠物收养所 啦啦啦啦 不维护区间的平衡树题都是树状数组+二分练手题! 不会的参考我的普通平衡树的多种神奇解法之BIT+二分答案 // It is made by X ...

  10. [转]关于PreparedStatement.addBatch()方法

    Statement和PreparedStatement的区别就不多废话了,直接说PreparedStatement最重要的addbatch()结构的使用. 1.建立链接,(打电话拨号 ) Connec ...