题目分享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条边的最短路径 ...
随机推荐
- 全方位认识HBase:一个值得拥有的NoSQL数据库(一)
前言:说起HBase这门技术,在认知上对于稍微接触或使用过它的人来讲,可能只是百千数据库中一个很普通的库,大概就像我对Redis的认知一样:缓存嘛!可对于HBase,我确实是带着某些感情在的.今日突然 ...
- mysql 向上取整
SELECT CEILING(10.0) --->10 SELECT CEILING(10.1) --->11
- Jquery+php鼠标滚动到页面底部自动加载更多内容,使用分页
1.index.php <style type="text/css"> #container{margin:10px auto;width: 660px; border ...
- windows编译动态链接库,dll+lib的形式
之前一直在linux上做开发,没怎么关注过windows上如何编译动态链接库.不过一直存疑,为什么windows上的动态链接库是.dll配合.lib使用的,这个又是怎么生成的呢,通过一段时间的查资料和 ...
- [Laravel] 自带分页实现以及links方法不存在错误
自带分页实现其实挺简单的,但是我在实现的时候报错!找了很久才找出原因! 废话不说上码 控制器LeeController.php层 <?php namespace App\Http\control ...
- HBase Filter 过滤器概述
abc 过滤器介绍 HBase过滤器是一套为完成一些较高级的需求所提供的API接口. 过滤器也被称为下推判断器(push-down predicates),支持把数据过滤标准从客户端下推到服务器,带有 ...
- python 获取的json字符串取值
获取到的json字符串,然后对其取值 {u'result': {u'10.10.10.100': {u'status': u'OK', u'msg': u"{'listen': {'': s ...
- Mysql中的一些类型
列类型--整数类型Tinyint:迷你整形 一个字节=8位 最大能表示的数值是0-255 实际区间 -128~127Smallint:小整形 两个字节 能表示0-65535Mediumint:中整型 ...
- 用Python打造电脑人脸屏幕解锁神器附带接头暗号!
前言 最近突然有个奇妙的想法,就是当我对着电脑屏幕的时候,电脑会先识别屏幕上的人脸是否是本人,如果识别是本人的话需要回答电脑说的暗语,答对了才会解锁并且有三次机会.如果都没答对就会发送邮件给我,通知有 ...
- Java IO 流 -- 转换流: InputStreamReader OutputStreamWriter
java 中 转换流是以字符流的形式操作字节流,需要注意一下两点: 1.操作内容必须是纯文本 2.指定字符集避免乱码 操作控制台输入输出: try (BufferedReader br = new B ...