题目分享Q
题意:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
分析:这可以说是换根法的裸题吧
首先考虑对一个给定的根如何计算,这应该是最简单的那种树形dp吧甚至可能都不算dp(好像还真不算dp)
dp[i]表示i点所有孩子(包括自己)的深度之和
deep[i]表示i点的深度
dp[x]=sum(dp[v]) +deep[x] v|v是x的子节点
用一遍dfs即可搞定dp[1]-dp[n]
当然这里用谁为根都可以,用1就行
比如我们现在已经处理出dp[1]-dp[n]的值
因为如果我们用2做根的时候,虽然发现所有人的dp值都改变了(每个人深度都改变了),这与我们之前学习的换根法可能会有一点区别
但能发现的是,我们当前根节点的儿子想上位所需要改变的东西(dp值)其实O(1)就可以解决,或者说有规律可言,所以我们可以用换根法
那么怎么改变?或者说有什么规律?
首先要先记住一点的还是那个状态转移方程 dp[x]=sum(dp[v]) +deep[x] v|v是x的子节点
再考虑这里面中每一项都怎么变的
就拿原来根是1换成2来说
首先,1除了2以外的子树的所有节点包括1在内(1,3,6,7,8),深度都+1
而2的子树包括2在内(2,3,5),深度都-1
然后好像就没啥别的变化了
那么再看dp值是怎么变的
首先dp[1]的值要先减去dp[2]的值,得到1除了2以外的子树包括1在内的深度之和,而得到这个之和dp[1]还要加上这些节点的个数,因为每个节点的深度都加一嘛
用son[i]表示i的子节点个数(包括自己)
也就是说dp[1]=dp[1]-dp[2]+(son[1]-son[2])(这是1除了子树2以外的节点数目)
而dp[2]是要先减去节点个数,再加上当前1的dp值(dp[1]修改后的值),因为此时1已经是2的儿子了
dp[2]=dp[2]-son[2]+dp[1]
注意这里是有先后顺序的
当然我们在第一遍dfs的时候要多算一遍son[i]
还有一点细节
在我们换根的时候要记得dfs完这个子树要还原成原来的样子再dfs下一个子树,而我们在dfs子树的时候其实与根节点是没有关系的,dfs只能往下搜嘛
也就是说我们在交换1和2的时候dp[1]的值不需要修改,所以我直接把dp[1]的式子带入到dp[2]的式子里就行了,也就是
dp[2]=dp[2]-son[2]+dp[1]-dp[2]+son[1]=dp[1]+son[1]-son[2]*2
最后把以所有点为根的结果取个最值就行了
代码:
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std; #define ll long long const int maxn=1e6+; struct Node
{
int to,next;
}e[maxn<<];
int head[maxn];
ll dp[maxn];
int son[maxn];
int cnt,k,n;
ll maxans; void add(int x,int y)
{
e[++cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt;
} void dfs1(int x,int fa,int now)
{
dp[x]=(ll)now,son[x]=;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa)
{
dfs1(v,x,now+);
dp[x]+=dp[v];
son[x]+=son[v];
}
}
} void dfs2(int x,int fa)
{
if(dp[x]>maxans||dp[x]==maxans&&x<k) k=x,maxans=dp[x];
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa)
{
ll now=dp[x]-dp[v]+(ll)son[x]-(ll)son[v]*;//这里是为了方便还原,下面用的+=和-=
int nowv=son[v];
son[v]=son[x];
dp[v]+=now;
dfs2(v,x);
dp[v]-=now;
son[v]=nowv;
}
}
} int main()
{
int n,x,y;
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs1(,-,);dfs2(,-);
printf("%d",k);
return ;
}
题目分享Q的更多相关文章
- 题目分享E 二代目
题意:一棵点数为n的树,每个节点有点权,要求在树中中找到一个最小的x,使得存在一个点满足max(该点点权,该点相邻的点的点权+1,其他点的点权+2)=x 分析:首先要能把题目转化为上述题意 首先题目让 ...
- 题目分享C 二代目
题意:一个数列是由 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6.....组成,也就是1-1,1-2,1-3......并且如果遇到多位数也要拆成数字比如1-10 ...
- 题目分享X
题意:一张票有n位数,如果这张票的前一半数字的和等于后一半数字的和(n一定是偶数),就称这张票为快乐票.有些数被擦除了,标记为’?’(’?‘的个数也是偶数),现在Monocarp 和 Bicarp 进 ...
- 题目分享V
题意:现在两个人做游戏,每个人刚开始都是数字1,谁赢了就能乘以k^2,输的乘以k(k可以是任意整数,每次不一定相同)现在给你最终这两个人的得分,让你判断是否有这个可能,有可能的话Yes,否则No. 分 ...
- 题目分享T
题意:蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n),并保证所有的长度都是非负整数(即:可 能存在长度为0的蚯蚓).每一秒,神刀手会 ...
- 2019年腾讯PHP程序员面试题目分享
有需要学习交流的友人请加入交流群的咱们一起,有问题一起交流,一起进步!前提是你是学技术的.感谢阅读! 点此加入该群jq.qq.com 1. php 的垃圾回收机制 PHP 可以自动进行内存管理,清除 ...
- 20190924-LeetCode解数独题目分享
解决数独 题目描述 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以 ...
- 题目分享F 二代目
题意:T个点R种双向边,P种单向边,求点S到每个点的最短距离 分析:(这再看不出来是spfa就该**了) 首先,这题能否用spfa就看他是否有负环呗,显然,双向边的权值非负,单向边还有个啥政策,总之显 ...
- 题目分享D 二代目
题意:给定一个T条边的无向图,求S到E恰好经过N条边的最短路径 T≤100 N≤1000000 分析:(据说好像假期学长讲过) 首先很容易想到的是dp[i][j][k]表示从i到j经过k条边的最短路径 ...
随机推荐
- 搭建环境-git常见使用总结
Descripton:git 一.Git安装和本地用户全局配置 官网下载并且安装 查看是否安装成功win + R输入git,出现git命令指南,则安装成功 全局配置本地用户,在git Bash中进行下 ...
- k8s Service学习
service的概念 kubernetes service定义了一个抽象概念,一个pod的逻辑分组,一种可以访问的策略---通常称为服务.这组pod能够被service访问到,通常通过label se ...
- lr自带协议工具
Lr自带的协议分析的工具: 录制脚本之前,选对协议很关键,否则错误的协议会导致Virtual User Generator 录制不到脚本,或录制的脚本不完整,有些应用可能需要选择多个协议才能完整的记录 ...
- Python 文件拼接
# -*- coding:utf-8 -*- import re import csv file = open('make_setup.cfg', 'w+') with open("tyb. ...
- AJ学IOS 之微博项目实战(10)微博cell中图片的显示以及各种填充模式简介
AJ分享,必须精品 :一效果 如果直接设置会有拉伸等等的状况,这里主要介绍图片显示的一些细节 二:代码 代码实现其实很简单,微博当中用了一个photos来存放九宫格这些图片,然后用了一个photo类来 ...
- linux下的信号量PV操作进阶之路
一.同步和互斥机制 信号量 互斥锁 同步:指多个任务按照约定的先后次序相互配合来完成一件事情. 比如读线程等待写线程写完之后再去读. 二.信号量-P/V操作 P(s)含义: if(信号量>0) ...
- stand up meeting 12/7/2015
part 组员 今日工作 工作耗时/h 明日计划 工作耗时/h UI 冯晓云 ------------------ -- --------------------- --- PDF Rea ...
- stand up meeting 11/30/2015
part 组员 今日工作 工作耗时/h 明日计划 工作耗时/h UI 冯晓云 完善了UI的各项功能,弹窗的显示格式等方面的规范:解决logic部分调用该dll的问题:解决鼠标事件的捕捉中~ ...
- jmeter5.1.1 生成html报告
1.首先需要准备好 .jmx 脚本 2.修改jmeter.properties文件(把注解去掉,报告中才能展示所需信息) jmeter.save.saveservice.output_format=x ...
- Redis学习与应用-位图
什么是位图 位图bitmap是通过一个bit来表示某个元素对应的值或者状态,是由一组bit位组成,每个bit位对应0和1两个状态,虽然内部还是采用string类型进行存储,但是redis提供了直接操作 ...