834 树中距离之和

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

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

对于固定根节点的,我们应该使用树状dp:
dp[u]=∑v∈son(u)dp[v]+sz[v]dp[u]=\sum_{v\in son(u)} dp[v]+sz[v] dp[u]=vson(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;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383593.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

75 颜色分类

题目已经提示可以一遍扫描了但是我还是没有想到&#xff0c;其实双指针的想法我已经有了&#xff0c;但是一想到有问题就觉得无法实现。这也揭示了我思维上的问题&#xff1a;用一种方法解决问题遇到困难第一件事情不是想着如何攻克而是想着换一种方法。对自己的思维也不自信。…

141 环形链表

要求使用空间复杂度为O(1)的方法&#xff0c;可是我并没有想到。我想到的只有用一个哈希表记录一下所有访问过的节点。 题解给出的空间复杂度为O(1)的方法是使用两个指针&#xff0c;然后让一个一次跑一步&#xff0c;一个一次跑两步&#xff0c;如果跑的快的能追上跑的慢的就…

数据可视化【十五】

经验法则&#xff1a;在颜色不相邻的时候加上背景颜色颜色的个数为6~12比较好。 颜色其实很大程度上由背景决定而不是他本身决定。 D3 Scale-Chromatic 有许多颜色刻度&#xff0c;可以根据自己的需要进行选择。 参考论文&#xff1a;Practical Rules for Using Color in Cha…

Ubuntu修改/删除主目录下的中文文件夹

在Ubuntu的主目录下一般是有一些中文的目录&#xff0c;例如桌面&#xff0c;视频等等&#xff0c;还无法修改名称&#xff0c;在一群英文文件夹里面显得有些突兀&#xff08;Ubuntu终端下的中文一点也不好看&#xff09;&#xff0c;就想把这些文件夹修改一下&#xff0c;结果…

19 删除链表的倒数第N个

题目的意思很简单&#xff0c;就是删除一个链表倒数第N个节点。 需要用到链表的标准操作&#xff1a;快慢指针。 我们让一个快指针先指向第N个元素&#xff0c;这个时候快指针总比慢指针领先N个元素&#xff0c;等到快指针指向链表尾部的时候慢指针就指向需要删除的元素。 之前…

844. Backspace String Compare

题目的意思大概是有两个字符串&#xff0c;其中的#表示退格键&#xff0c;让比较最后两个字符串是否相当。 很容易想到的思路就是用一个栈进行模拟这个过程&#xff0c;特别需要注意如果一个串是空串也是可以退格的。 但是很容易想到的另一个特性就是&#xff0c;前面的字符有…

链表三连击

876&#xff1a;链表的中间节点 206&#xff1a;反转链表 143&#xff1a;重排练表 链表的中间节点 这个题一看就是最简单的快慢指针&#xff0c;但是在具体实现的时候我还是犹豫思考了一下&#xff1a;要不要在链表前面放置哑节点&#xff0c;快指针应该什么时候判断已经到达…

D3力导引图

学习力导引图的时候在网上没有找到什么好的教程&#xff0c;支离破碎地进行了一段时间的学习&#xff0c;还阅读了d3的关于d3的官方文档&#xff0c;但是始终觉得不的要领。这里记录一下我学习力导引图的一些心得以及推荐一下学习资源。 学习资源 官方文档&#xff1a;https:…

Ubuntu Pycharm启动后卡住无法操作

昨天还好好的&#xff0c;今天打开Pycham突然卡住了&#xff0c;卡在了那个preparing workspace的地方&#xff0c;然后在网上搜索了很多方法都没用。直到在网上看到有个大佬说是因为搜狗输入法的问题&#xff0c;我才突然记起来昨天安装了搜狗输入法。。。 kill掉卡住的Pycha…

327 区间和的个数

题目描述 Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive. Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive. Note: A naive algorithm of O(n2) is t…

浏览器访问本地文件

之前一直苦恼无法在浏览器访问本地文件&#xff0c;尤其是写的网页需要调用外部数据的时候&#xff0c;今天学习到可以用python很方便的解决问题 如果有python3环境&#xff0c;直接在对应的文件夹下运行&#xff08;这里是Ubuntu环境&#xff0c;如果是Windows应该在命令行也…

Ubuntu使用jupyter notebook +导出PDF

因为最近需要做数据分析的工作&#xff0c;所以复习了一下numpy和pandas&#xff0c;并安装了jupyter notebook进行数据分析&#xff0c;这里记录一下环境的设置。 ps:jupyter notebook真香 安装 python3 -m pip install --upgrade pip //升级pip pip3 install jupyter使用 …

SSH:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

给服务器重装了一下系统&#xff0c;结果报了上述错误&#xff1a; WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! ...在网上找…

Ubuntu20.04 更新后黑屏无法加载驱动

本来我的电脑好好的&#xff0c;突然提示说有可应用的更新&#xff0c;我想都没想就直接更新了&#xff0c;可是没想到更新以后经过grub以后就会黑屏&#xff0c;一动不动&#xff0c;在网上搜索了许多&#xff0c;提到的说法是在grub界面对第一个Ubuntu的启动按e进行编辑 在倒…

每日一题:leetcode1489. 找到最小生成树里的关键边和伪关键边

时隔多年我终于又开始写博客了&#xff0c;主要是已经放假了&#xff0c;之前一直忙于考试和课设没有时间写博客&#xff0c;学习笔记也因为买了iPad的缘故大部分都是手写的了。 假期想要把以前做过的项目都整理一下放在github和CSDN上。 也已经很久没有写算法题了&#xff0…

每日一题:leetcode989.数组形式的整数加法

题目描述 题目分析 题目非常简单&#xff0c;但是我还是wa了几发&#xff0c;对不起&#xff0c;我太菜了。我的想法是把K转换为数组然后用大整数加法处理。但是因为太久没有写了导致写了好久。 class Solution { public:void add(vector<int> &A, vector<int&g…

每日一题:leetcode674.最长连续递增序列

题目描述 题目分析 一遍遍历&#xff0c;如果硬要说用了什么算法的话觉得应该算是一个简单的滑动窗口吧 AC代码 class Solution { public:int findLengthOfLCIS(vector<int>& nums) {if (nums.size() 0) {return 0;}int ret 1;int cnt 1;for (int i 1; i <…

每日一题:leetcode959.由斜杠划分区域

题目描述 题目分析 仔细分析这道题以后虽然觉得可能要转化为图之类的&#xff0c;但是完全没有具体的想法&#xff0c;因为每个格子都有三种情况&#xff0c;这三种情况的不同的组合又会产生不同的结果。 发现找不到编码转化为图以后&#xff0c;我分析了一下不同数量方块之间…

每日一题:leetcode1319.联通网络的操作次数

题目描述 题目分析 ps&#xff1a;这篇博客是补前天的&#xff0c;前天在老家不方便写博客 题目挺简单的&#xff0c;但是通过题目对图的连通性有了一个更深刻的认识&#xff1a;如果有超过&#xff08;或等于&#xff09;n-1条边&#xff0c;则一定是可以让整个图联通的。 如…

每日一题:leetcode1128.等价多米诺骨牌对数

题目描述 题目分析 看到题目以后第一个想法是遍历数组&#xff0c;对每个元素有一个数据结构中保存了该元素出现的次数&#xff0c;然后往结果中相加&#xff08;表示该元素和前面的对数&#xff09;&#xff0c;然后再将元素出现的次数加一。 思考用什么数据结构保存元素出现…