首页 > 其他分享 >树形DP+树上路径贡献

树形DP+树上路径贡献

时间:2024-04-01 22:24:43浏览次数:22  
标签:f1 伤害 路径 son 100005 树形 节点 DP

题目

一棵树有n个节点,每个节点都同有一个符号+或者-,表示该节点是正极节点还是负极节点。如果从正极走到负极,或者从负极走到正极,都会受到1点伤害。
现在需要知道走过所有路径后会受到的总伤害是多少?树上任意2点存在唯一的路径。需要计算所有任意2点的路径的伤害和。

注意:从u到,和从v到u视为同一条路径。

输入描述

第一行输入一个整数n(1≤n ≤ 10^5 )
第二行输入一个长度为1的仅由+和-组成的字符串。
接下来n-1 行,每行输入两个整数 u,v(1≤u,v≤n) 表示节点
u和节点v之间有一条边。

输出描述

输出一个整数表示受到的总伤害。

样例1

输入

3
++-
1 2
1 3

输出
2

说明
路径1-2 (2-1) 不会受到伤害。
脂径1-3(3-1) 会受到1点伤害。
路径2-1-3(3-1-2)会受到1点害。
因此答案为2。

题目分析

典型的树形DP,换根可以解决路径去重的问题。现在考虑怎么计算贡献。
我们可以很容易想到一个f[i]: i的子树上所有经过点i的路径的伤害值的和。那么$ \sum\limits_{1}^{n} f[i]$就是答案

image
在DFS时到1的时候,考虑1-3的边,在考虑2和3的子树合并的时候计算f[1], 当前增加的路径是,根(1,2,4,5)到3点所有子树(3, 6)的路径。因为每条路径一定会经过1。 对每条路径进行拆分, \((X - Y) = (X - 1) + (1 - Y)\)
X是(1,2,4,5),Y是(3, 6)。
每个X会和每个Y匹配出一条路径,那么对于X-1会被计算Y次。对于每个根u,我们求出它的字树到根u的路径和\(f1[u] = \sum\limits^{x=所有的子节点} (x 到u的路径伤害)\)
那么这个公式
\((X - Y) = (X - 1) + (1 - Y)\)
转化成
\(f[u] = f1[u] * son[to] + f1[to] * son[to]\)

f1[to]在计算前,应该处理u-to这条边的伤害。

代码如下:

#include <iostream>

using namespace std;

char ch[100005];
bool vis[100005];
vector<int> G[100005];
long long f[100005], f1[100005], son[100005];

void Dfs(int u, int fa){
    son[u] = 1;
    for (auto to : G[u]) {
        if (to != fa) {
            Dfs(to, u);
            // 处理边u-to的伤害
            if (ch[u] != ch[to]) {
                f1[to] += son[to];
            }
            // 计算贡献
            f[u] += f1[u] * son[to] + f1[to] * son[u];
            // 换根
            f1[u] += f1[to];
            son[u] += son[to];
        }
    }
}

int main() {
    
    int  n; scanf("%d", &n);
    scanf("%s", ch+1);
    for(int i=1; i<n; i++) {
        int a, b; scanf("%d%d", &a, &b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    long long ans = 0;
    Dfs(1, 0);
    for (int i=1; i<=n; i++) {
        ans += f[i];
    }
    printf("%lld\n", ans);
    
    return 0;
}
/*
7
++--+-+
1 2
2 3
2 4
3 5
1 6
6 7
 
5
+-++-
1 2
2 3
2 4
1 5
 
3
+--
 1 2
 1 3
 
 8
+-++-+-+
 1 2
 2 3
 3 4
 3 5
 1 6
 6 7
 6 8
 
*/

标签:f1,伤害,路径,son,100005,树形,节点,DP
From: https://www.cnblogs.com/liweihang/p/18109497

相关文章

  • 2642. 设计可以求最短路径的图类(中等)
    核心思想Dijkstra+堆优化模板题,每次查询做一次最短路查询即可。classGraph{privateList<int[]>[]nxt;publicGraph(intn,int[][]edges){nxt=newList[n];for(inti=0;i<n;i++){nxt[i]=newArrayList<>();......
  • 引入了 Shiro 的项目请求路径中带有中文报错400 的问题
    byemanjusakafromhttps://www.emanjusaka.top/2024/04/shiro-request-chinese-error-400彼岸花开可奈何本文欢迎分享与聚合,全文转载请留下原文地址。当我们的项目中引入了Shiro后,带有中文的请求路径会被拦截并返回400的错误。一般我们的请求路径是不会带有中文字符,但......
  • macbook pip3路径报错
    执行pip3,提示:zsh:/usr/local/bin/pip3:badinterpreter:/Library/Developer/CommandLineTools/usr/bin/python3:nosuchfileordirectory问题:原因:python路径不正确方法:➜whichpython3/usr/local/bin/python➜bincd/usr/local/bin➜binvimpip3修改第一......
  • 【二叉树】Leetcode 437. 路径总和 III【中等】
    路径总和III给定一个二叉树的根节点root,和一个整数targetSum,求该二叉树里节点值之和等于targetSum的路径的数目。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。示例1:**输入:**root=[10,5,-3,3,2,null,11,3,......
  • 2673. 使二叉树所有路径值相等的最小代价
    思路先看3节点的子树,想要路径值相同,只能修改叶子节点的值,如上图只能2去+1操作。核心思想:那么对于任意左右孩子节点,想要从根节点下来的路径相同,只能修改孩子节点。所以我们只需要从下至上记录叶子节点到当前节点的路径值,然后计算当前节点和右节点的差值。详细看灵神树上贪心......
  • 如何查看已安装的python路径?
    在Windows、Linux或Mac中,Python都是非常流行的编程语言。查看已安装的Python路径是学习Python开发的基础之一。下面我们就来分享一下如何查看已安装的Python路径?如何查看已安装的python路径?1.在Windows中首先,打开Windows命令提示符。在开始菜单中输入“cmd”并打开它。然后输入......
  • Offer必备算法17_子数组子串dp_八道力扣题详解(由易到难)
    目录①力扣53.最大子数组和解析代码②力扣918.环形子数组的最大和解析代码③力扣152.乘积最大子数组解析代码④力扣1567.乘积为正数的最长子数组长度解析代码⑤力扣413.等差数列划分解析代码⑥力扣978.最长湍流子数组解析代码⑦力扣139.单词拆分解析代码......
  • Offer必备算法19_子序列dp_八道力扣题详解(由易到难)
    目录①力扣300.最长递增子序列解析代码②力扣376.摆动序列解析代码③力扣673.最长递增子序列的个数解析代码④力扣646.最长数对链解析代码⑤力扣1218.最长定差子序列解析代码⑥力扣873.最长的斐波那契子序列的长度解析代码⑦力扣1027.最长等差数列解析代......
  • wordpress负载均衡
    部署的顺序先有后端web7,8,再有前端的lb-5。web7#装nginxgroupaddwww-g666useraddwww-s/sbin/nologin-M-u666-g666#你要确保,你装的所有机器,软件版本都一致,否则可能出奇怪bug#web7,web8用同一套软件,你最好自己去自建yum源cat>/etc/yum.repos.d/61.repo......
  • Matlab构建上位机:UDP测试
    参考:UDP理解及UDP的MATLAB实现MatlabUDP-CSDN博客文中代码:建立连接fclose(instrfindall);%先关闭之前可能存在的UDP%127.0.0.1即为本地u1=udp('127.0.0.1','RemotePort',8847,'LocalPort',8848);%u1的本机端口为8848,即监听所有发到8848端口的消息;%u1的远程端口为8847,......