这道题我自己的想法只有对每个点都用一遍Dijkstra然后再求和,显然会超时,所以我都没有尝试。

研究了一下题解,发现题解很巧妙,自己对树的处理还是太稚嫩,之前树链剖分学的都忘光了。

对于固定根节点的,我们应该使用树状dp:
dp[u]=∑v∈son(u)dp[v]+sz[v]dp[u]=\sum_{v\in son(u)} dp[v]+sz[v] dp[u]=v∈son(u)∑​dp[v]+sz[v]
其中,dp[u]dp[u]dp[u]表示以u为根节点的子树中根节点u到其儿子节点的所有距离之和,之所以加上sz[v]sz[v]sz[v]是因为长度为1,如果长度不固定的话只需要乘上长度就可以了。

通过上面的dp我们可以算出以一个节点为根节点的答案,但是其他节点呢?朴素的想法是对其他节点每个也进行相同的操作,这样的时间复杂度是O(n2)O(n^2)O(n2),好像还可以接受。

题解给出了更优秀的做法:假设我们已经求出了以节点u为根节点的树的答案dp[u]dp[u]dp[u],对于其直接孩子v,我们是有办法直接求出以v为根节点的答案的。

最主要的性质是:如果更换了根节点,只会影响这两个相邻节点的dp值,对其他节点的dp值是不会有影响的。因此我们只需要更新这两个节点即可。

首先我们应该从dp[u]dp[u]dp[u]中减去dp[v]+sz[v]dp[v]+sz[v]dp[v]+sz[v],因为这个时候是以v为根节点的,然后更新sz[u]sz[u]sz[u],然后再给dp[v]dp[v]dp[v]加上dp[u]+sz[u]dp[u]+sz[u]dp[u]+sz[u],再更新sz[v]sz[v]sz[v]。这样就得到了正确的答案。

代码实现的话首先进行一次树状dp,然后再进行回溯。

发现题解中的代码很精炼,仔细学习了一下自己实现了一个差不多的,几乎没有区别。学到了使用emplace_backemplace\_backemplace_back的复杂度好像更加优秀。

还是要多做hard题目,对自己的提升比较大。

class Solution {public:vector<int> dp,sz,ans;vector< vector<int> > graph;void Init(int n, vector<vector<int> >&edges){dp.resize(n, 0);sz.resize(n, 0);ans.resize(n, 0);graph.resize(n, {});int u,v;for(auto& edge:edges){u = edge[0]; v = edge[1];graph[u].emplace_back(v);graph[v].emplace_back(u);}}void dfs(int u,int father){sz[u] = 1; dp[u] = 0;for(auto& v:graph[u]){if(v == father) continue;dfs(v, u);sz[u] += sz[v];dp[u] += dp[v] + sz[v];}}void dfs2(int u, int father){ans[u] = dp[u];int dpu, dpv, szu, szv;for(auto& v:graph[u]){if(v == father) continue;dpu = dp[u]; dpv = dp[v];szu = sz[u]; szv = sz[v];dp[u] -= dp[v] + sz[v];sz[u] -= sz[v];dp[v] += dp[u] + sz[u];sz[v] += sz[u];dfs2(v, u);dp[u] = dpu; dp[v] = dpv;sz[u] = szu; sz[v] = szv;}}vector<int> sumOfDistancesInTree(int N, vector<vector<int>>& edges) {Init(N, edges);dfs(0, -1);dfs2(0, -1);return ans;}
};

834 树中距离之和相关推荐

  1. 834. 树中距离之和

    834. 树中距离之和 解法一:超时的暴力解法 #include <iostream> #include <vector> #include <string> #i ...

  2. leetcode 834. 树中距离之和(dp)

    给定一个无向.连通的树.树中有 N 个标记为 0...N-1 的节点以及 N-1 条边 .第 i 条边连接节点 edges[i][0] 和 edges[i][1] .返回一个表示节点 i 与其他所有节 ...

  3. LeetCode 834. 树中距离之和(树上DP)*

    文章目录 1. 题目 2. 解题 1. 题目 给定一个无向.连通的树.树中有 N 个标记为 0...N-1 的节点以及 N-1 条边 . 第 i 条边连接节点 edges[i][0] 和 edges[ ...

  4. leetcode 834. Sum of Distances in Tree | 834. 树中距离之和(树形DP)

    题目 https://leetcode.com/problems/sum-of-distances-in-tree/ 题解 一般的算法题,指令条数为 10^8 以内是可以通过的.也就是说,如果 arr ...

  5. 树形动态规划 - 树中距离之和

    题目链接 换根dp 首先dfs记录每个节点到左右子节点的距离和sum,和子节点个数cnt. 已知父节点的(sum,cnt)如何向子节点转移? 假设当前节点的信息为(sum,cnt),父节点的信息为(F ...

  6. 利用最小二乘法,用直线拟合点时,为什么计算竖直距离而非垂直距离?为什么在线性回归分析中,求的是距离平方和最小,而不是距离之和最小?

    我的理解是,直接求距离之和可能导致多个解存在的情况,而求距离平方和可以保证唯一解,参考: 当且仅当a=b时,不等式等号成立 参考文章:利用最小二乘法,用直线拟合5点时,为什么计算竖直距离而非垂直距离?

  7. 51nod 1096 距离之和最小 思维题,求中位数

    题目: 在一条直线上,与两个点距离之和最小的点,是怎样的点? 很容易想到,所求的点在这两个已知点的中间,因为两点之间距离最短. 在一条直线上,与三个点距离之和最小的点,是怎样的点? 由两个点的规律,我 ...

  8. 关于货仓选址问题的方法及证明(在数轴上找一点使得该点到所有其他点的距离之和最小)...

    在数轴上找一点使得该点到所有其他点的距离之和最小 方法:找到大小为中位数的点,该点就是要求的点(如有两个取之间任意一点都行) 证明: 先看看当只有2个点时的情况: 分类讨论: 如果在A的左边(如 $P ...

  9. 1405 树的距离之和

    1405 树的距离之和 基准时间限制:1 秒 空间限制:131072 KB 给定一棵无根树,假设它有n个节点,节点编号从1到n, 求任意两点之间的距离(最短路径)之和. Input 第一行包含一个正整 ...

最新文章

  1. C++运行时类型信息 (RTTI)
  2. Code128条形码
  3. mysql和sql互导_Mysql和SqlServer互相转换
  4. python字符串前加r、f、u、l 的区别
  5. Vue项目实战06:nprogress页面加载进度条
  6. 中虚数怎么表示_英文论文写作中的常见错误
  7. 【CF594E】Cutting the Line 【贪心】【Lyndon Word】【扩展kmp】
  8. PHP——0128练习相关1——window.open()
  9. Docker可视化界面(Consul+Shipyard+Swarm+Service Discover
  10. 题目1120:全排列
  11. 微信小程序 java后勤服务管理系统app
  12. 经典游戏制作教程[zz]
  13. python句柄无效_python免注册调用大漠出现错误句柄无效
  14. ocr文字识别html,在线OCR 随时随地轻松搞定文字识别
  15. 迷宫(Maze)项目实现
  16. Riverbed为用户优化网络效能并保护数据安全
  17. 服务器租用idc机房功能和配置介绍
  18. ImportError: DLL load failed while importing qhull:问题解决
  19. 安卓文件传输工具 Android File Transfer mac
  20. CocosCreator解决微信网络并发数大于10的问题

热门文章

  1. jenkins jar包上传maven仓库
  2. bzoj4152: [AMPPZ2014]The Captain
  3. 使用maven插件构建docker镜像
  4. 【javascript】DOM操作方法(3)——document节点属性
  5. day04_09 while循环03
  6. python_day7 绑定方法与非绑定方法
  7. SpringMVC搭建+实例
  8. 利用jenkins的api来完成相关工作流程的自动化
  9. 控制器中获取Field值
  10. 一个把图片保存到SQL数据库的工具