题目

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

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

\(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. 20155333 2016-2017-2 《Java程序设计》第4周学习总结

    20155333 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 继承基本上就是避免多个类间重复定义的共同行为,在Java中,子类只能继承一个父类. priv ...

  2. Wiki版产品需求---产品需求文档到底是谁的?产品到底是谁的?

    在听了测试的一通唠叨之后,"内部实现一堆逻辑,只有一句话的需求文档","文档那么简单,我们怎么测试啊",心中突然想起来自己曾经干的一件当时觉得还不错的事情,但是 ...

  3. XDS100V3连接Pandaboard ES OMAP4460开发板

    1. 硬件连接如下 2. 使用CCS创建工程,不过好像没有ARM9的内核吧?为啥会出现? 3. 创建目标配置文件 4. 不过确实有ARM9的内核,两个A9内核,一个DSP C64X内核,两个M3的内核 ...

  4. mysql-5.7.17-winx64免安装版环境配置 问题小记

    安装版问题请自行百度或google 这里总结几个免安装版mysql-5.7.17-winx64配置后,出现问题的解决方法. 具体的环境配置请先参考mysql-5.7.17-winx64免安装版,win ...

  5. 基于ejabberd简单实现xmpp群聊离线消息

    首先,xmpp服务器是基于ejabberd.离线消息模块是mod_interact,原地址地址:https://github.com/adamvduke/mod_interact: 修改后实现群聊离线 ...

  6. Linux学习(一)------CentOs安装mysql5.5 数据库

    具体方法和步骤如下所示: 1.第一步就是看linu是否安装了mysql,经过rpm -qa|grep mysql查看到centos下安装了mysql5.1,那就开始卸载咯 2.接下来就是卸载mysql ...

  7. 获取安卓app的appPackage和appActivity

    1.需要配置好android的开发环境后,打开cmd命令窗口 2.在命令窗口中输入,adb logcat>D:/log.log,抓取日志 3.运行启动app 4.查看日志log 5.搜索日志的关 ...

  8. [C++]boost dijkstra获得两点间的最短路

    需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...

  9. Mybatis-Plus的填坑之路 - Lynwood/wunian7yulian

    目录 Mybatis-Plus 我来填坑~ 目录 一.简单介绍 官方说明 : 成绩: 最新版本: 开发层面MyBatis-Plus特色 Mybatis-Plus中的Plus 二.MP的特性 三.MP框 ...

  10. java 乐观锁 vs 悲观锁

    在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性. 悲观锁其实就是 完全同步 比如 sync ...