洛谷同步博客

1.我们先来简化一下问题

如果题目不让我们改造这棵树,就很好求了。
先求出size[e]size[e]size[e](如下图),eee为无根树中的任意一条有向边(我们在邻接表中使用一对有向边eee和e‾\overline{e}e来表示,其中e‾\overline{e}e为eee的反向边,表示以tail[e]tail[e]tail[e](表示边e的尾)为根的子树的大小。可知size[e‾]=n−size[e]size[\overline{e}]=n-size[e]size[e]=n−size[e]。

要求出size[e]size[e]size[e]和size[e‾]size[\overline{e}]size[e],可以用一个dfsdfsdfs来解决(e‾\overline{e}e可以用一个小技巧:e^1

上代码:

void dfs(int u,int e)
{size[e]=1;for(int i=0;i<(int)G[u].size();i++)if(G[u][i]!=(e^1)){int v=edges[G[u][i]].v;dfs1(v,G[u][i]);add(u,G[u][i]);size[e]+=size[G[u][i]];}size[e^1]=n-size[e];
}

这样,就可以了:把每个节点的各个子节点的sizesizesize值扫描一遍,有size[v]≥n2(v∈son[u])size[v]≥\frac{n}{2}(v\in son[u])size[v]≥2n​(v∈son[u])就说明uuu不是树的中心。

2.说了半天,回到原问题(还有啊!qwqqwqqwq!)

做好迎接挑战的准备吧!

我们要把一条边删去,并连上另一条新边,也就是说,要把一个子树切割下来,在把他连到新的节点上。
我们可以计算一个c[e]c[e]c[e](eee的定义同size[e]size[e]size[e]),表示以tail[e]tail[e]tail[e]为根的子树中最多可以割下多少个节点,可知c[e]≤n2c[e] \le \frac{n}{2}c[e]≤2n​。
可以在原来的dfsdfsdfs的基础上再加一个dfsdfsdfs(并用一个数据结构来辅助实现):

void add(int u,int i)
{if(best[u]<=c[i]){sec[u]=best[u];best[u]=c[i];idx[u]=i;}else sec[u]=max(sec[u],c[i]);
}
int query(int u,int i)
{if(i!=idx[u]) return best[u];else return sec[u];
}
void dfs1(int u,int e)
{size[e]=1;c[e]=0;for(int i=0;i<(int)G[u].size();i++)if(G[u][i]!=(e^1)){int v=edges[G[u][i]].v;dfs1(v,G[u][i]);add(u,G[u][i]);size[e]+=size[G[u][i]];c[e]=max(c[e],c[G[u][i]]);}size[e^1]=n-size[e];if(size[e]<=n/2) c[e]=size[e];
}
void dfs2(int u,int e)
{add(u,e^1);for(int i=0;i<(int)G[u].size();i++)if(G[u][i]!=(e^1)){if(size[G[u][i]^1]<=n/2) c[G[u][i]^1]=size[G[u][i]^1];else c[G[u][i]^1]=query(u,G[u][i]);dfs2(edges[G[u][i]].v,G[u][i]);}
}

3.于是我们就大功告成了

献上我丑陋的代码:

#include<iostream>
#include<vector>
using namespace std;
const int maxn=800005;
struct Edge
{int u,v;Edge(int x,int y): u(x),v(y){}
};
int n,size[maxn],c[maxn],best[maxn],sec[maxn],idx[maxn];
vector<Edge> edges;
vector<int> G[maxn];
void add(int u,int i)
{if(best[u]<=c[i]){sec[u]=best[u];best[u]=c[i];idx[u]=i;}else sec[u]=max(sec[u],c[i]);
}
int query(int u,int i)
{if(i!=idx[u]) return best[u];else return sec[u];
}
void dfs1(int u,int e)
{size[e]=1;c[e]=0;for(int i=0;i<(int)G[u].size();i++)if(G[u][i]!=(e^1)){int v=edges[G[u][i]].v;dfs1(v,G[u][i]);add(u,G[u][i]);size[e]+=size[G[u][i]];c[e]=max(c[e],c[G[u][i]]);}size[e^1]=n-size[e];if(size[e]<=n/2) c[e]=size[e];
}
void dfs2(int u,int e)
{add(u,e^1);for(int i=0;i<(int)G[u].size();i++)if(G[u][i]!=(e^1)){if(size[G[u][i]^1]<=n/2) c[G[u][i]^1]=size[G[u][i]^1];else c[G[u][i]^1]=query(u,G[u][i]);dfs2(edges[G[u][i]].v,G[u][i]);}
}
int main()
{cin>>n;for(int i=1;i<n;i++){int u,v;cin>>u>>v;edges.push_back(Edge(u,v));edges.push_back(Edge(v,u));G[u].push_back(edges.size()-2);G[v].push_back(edges.size()-1);}dfs1(1,edges.size());dfs2(1,edges.size());for(int i=1;i<=n;i++){bool ok=true;for(int j=0;j<(int)G[i].size();j++)if(size[G[i][j]]-c[G[i][j]]>n/2){ok=false;break;}cout<<ok<<' ';}return 0;
}

P.S.:P.S.:P.S.:如有不当,请指出。

CF708C 【Centroids】树上DP相关推荐

  1. 【ZJOI2019】线段树【线段树上dp】【大讨论】

    题意:有一个 [1,n][1,n][1,n] 的线段树和 mmm 个区间赋值操作,求任取一个操作的子集并按顺序在线段树上跑后线段树上有 lazy 标记的点的个数之和 模 998244353998244 ...

  2. 牛客网CSP-S提高组赛前集训营1题解(仓鼠的石子游戏 [博弈论] + 乃爱与城市的拥挤程度 [树上DP] + 小w的魔术扑克[dfs + 离线])

    文章目录 T1:仓鼠的石子游戏 题目 题解 代码实现 T2:乃爱与城市拥挤程度 题目 题解 代码实现 T3:小w的魔术扑克 题目 题解 代码实现 T1:仓鼠的石子游戏 题目 仓鼠和兔子被禁止玩电脑,无 ...

  3. 警卫站岗(树上dp)

    题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...

  4. bzoj2435: [Noi2011]道路修建 树上dp

    点击打开链接 RE了一辈子... 思路:树上dp,直接dfs找到每个点v的子节点有多少, 那么对答案的贡献是 w*abs((n-size[v])-size[v]); RE代码: 1 #include ...

  5. P3387 【模板】缩点 Tarjan强连通分量/树上dp

    P3387 [模板]缩点 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 首先,什么是强连通分量 极大强连通子图 叫做强连通分量             首先要明确,         ...

  6. 2019长安大学ACM校赛网络同步赛C LaTale (树上DP)

    链接:https://ac.nowcoder.com/acm/contest/897/C 来源:牛客网 LaTale 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 32768K,其他 ...

  7. 算法提高——树上DP(树的直径)

    文章目录 前言 一.什么是树的直径? 二.例题 三.树上DP 总结 前言 树的直径是图论里边非常高的考察点并且是入门树形dp的基础,竞赛的同学务必重视. 一.什么是树的直径? 树上最远两点(叶子结点) ...

  8. Codeforces Round #699 (Div. 2) F - AB Tree(贪心、树上DP)超级清晰,良心题解,看不懂来打我 ~

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Codeforces Round #699 (Div. 2) F - AB Tree Problem ...

  9. 洛谷P4322 最佳团伙(树上dp)

    题目描述 洛谷传送门 题目描述 JSOI 信息学代表队一共有 N 名候选人,这些候选人从 1 到 N 编号.方便起见,JYY 的编号是 0 号.每个候选人都由一位编号比他小的候选人Ri推荐.如果 Ri ...

最新文章

  1. CSS和HTML做好看的界面
  2. sess.run的错误
  3. 台式计算机的配置清单(硬件和软件),台式电脑的配置清单和产品推荐
  4. 一篇文章教你如何使用python爬虫
  5. bzoj 1225 暴搜动态规划
  6. java线程内存模型_深度解析Java多线程的内存模型
  7. HashSet,TreeSet和LinkedHashSet的区别
  8. php files得不到导入的文件,PHP判断文件是否被引入的方法get_included_files用法示例...
  9. Objective-C中的面向对象编程
  10. 这几个动态规划的问题,面试官就爱问
  11. oracle12c xtts迁移,记录一次XTTS迁移碰到的问题
  12. 弱监督学习-snorkel
  13. Html Imput 的用法
  14. Log-normal distribution对数正态分布
  15. VSCode 和 CMake 搭建嵌入式开发环境
  16. 第十二周《支持SQl Server内部,第二版》CHAR1数据页面和数据行 作者Dmitri Korotkevitch
  17. (预处理合集)手写数据集MNIST(2)——Spyder
  18. 2020高考报计算机专业指南,2020高考志愿填报最全攻略
  19. matlab编写连续时间系统的时域分析
  20. python温度转换_python第一课:温度转换

热门文章

  1. 【机器学习PAI实战】—— 玩转人工智能之你最喜欢哪个男生?
  2. UE风格化Day4-maya建模-歇山顶屋顶
  3. [luogu3393]逃离僵尸岛
  4. SSD+HDD安装双系统(win10+Ubuntu16.04)
  5. 百格活动:人在江湖身不由己,山头黑话一定要了解
  6. android图片解码显示,android 图片解码显示流程
  7. 【dp】守望者的逃离
  8. 做自媒体工具和软件有哪些?整理8类工具分享给大家!
  9. linux之权限管理命令
  10. 2021年Java面试心得:阿里java开发面试