[洛谷-P3047] [USACO12FEB]Nearby Cows G(树形DP+换根DP)

news2024/11/25 10:52:35

[洛谷-P3047] [USACO12FEB]Nearby Cows G

  • 一、问题
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
  • 二、分析
    • 1、状态表示
    • 2、状态转移
    • 3、换根DP
  • 三、代码

一、问题

题目描述

Farmer John has noticed that his cows often move between nearby fields. Taking this into account, he wants to plant enough grass in each of his fields not only for the cows situated initially in that field, but also for cows visiting from nearby fields.

Specifically, FJ’s farm consists of N fields (1 <= N <= 100,000), where some pairs of fields are connected with bi-directional trails (N-1 of them in total). FJ has designed the farm so that between any two fields i and j, there is a unique path made up of trails connecting between i and j. Field i is home to C(i) cows, although cows sometimes move to a different field by crossing up to K trails (1 <= K <= 20).

FJ wants to plant enough grass in each field i to feed the maximum number of cows, M(i), that could possibly end up in that field – that is, the number of cows that can potentially reach field i by following at most K trails. Given the structure of FJ’s farm and the value of C(i) for each field i, please help FJ compute M(i) for every field i.

输入格式

* Line 1: Two space-separated integers, N and K.

* Lines 2…N: Each line contains two space-separated integers, i and j (1 <= i,j <= N) indicating that fields i and j are directly connected by a trail.

* Lines N+1…2N: Line N+i contains the integer C(i). (0 <= C(i) <= 1000)

第一行两个正整数 n , k n,k n,k
接下来 n − 1 n-1 n1 行,每行两个正整数 u , v u,v u,v,表示 u , v u,v u,v 之间有一条边。
最后 n n n 行,每行一个非负整数 c i c_i ci,表示点权。

输出格式

* Lines 1…N: Line i should contain the value of M(i).

输出 n n n 行,第 i i i 行一个整数表示 m i m_i mi

样例 #1

样例输入 #1

6 2 
5 1 
3 6 
2 4 
2 1 
3 2 
1 
2 
3 
4 
5 
6

样例输出 #1

15 
21 
16 
10 
8 
11

提示

There are 6 fields, with trails connecting (5,1), (3,6), (2,4), (2,1), and (3,2). Field i has C(i) = i cows.

Field 1 has M(1) = 15 cows within a distance of 2 trails, etc.

【数据范围】
对于 100 % 100\% 100% 的数据: 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105 1 ≤ k ≤ 20 1 \le k \le 20 1k20 0 ≤ c i ≤ 1000 0 \le c_i \le 1000 0ci1000

二、分析

题目简单地来说就是:
给你一棵 n n n 个点的树,点带权,对于每个节点求出距离它不超过 k k k 的所有节点权值和 m i m_i mi

对于树中的某个节点而言,距离它不超过 k k k的节点主要来源于两方面,一个是该节点的子节点中距离该节点不超过距离 k k k的节点的权值和,另一个就是该节点向上沿着父节点方向不超过距离 k k k的点的权值和。

对于子节点方向的节点的权值和,我们可以先通过普通的树形DP计算出来。

因此,我们先写一个DP计算出子树中距离该点不超过 k k k的点的权值和。

1、状态表示

f [ u ] [ k ] f[u][k] f[u][k]表示以 u u u为根节点的树中,距离 u u u不超过 k k k的子节点的权值和。

2、状态转移

f [ u ] [ k ] = v a l [ u ] + ∑ f [ s o n ] [ k − 1 ] f[u][k]=val[u]+\sum f[son][k-1] f[u][k]=val[u]+f[son][k1]
到节点 u u u不超过距离 k k k,即距离 s o n son son不超过 k − 1 k-1 k1,然后加在一起即可。同时 u u u节点本身也是答案,因为 u u u节点本身是不超过距离 0 0 0的节点。

3、换根DP

这个题目本身是个无根树,如果我们认为规定编号为1的节点是根的话,那么对于祖宗节点 1 1 1来说, f [ 1 ] [ k ] f[1][k] f[1][k]就是距离 1 1 1节点不超过距离 k k k的节点的权值和。因为祖宗节点是没有父亲节点的,所以我们就不需要考虑沿着父节点方向的节点权值和。

我们不妨令: g [ u ] [ k ] g[u][k] g[u][k]表示所有到 u u u节点的不超过距离 k k k的节点的权值和。根据刚刚的分析: g [ 1 ] [ k ] = f [ 1 ] [ k ] g[1][k]=f[1][k] g[1][k]=f[1][k]

这个就是我们换根DP的初始化。其实受这个的启发,我们完全可以去把每个点都当作根,然后暴力跑出答案,但是这个暴力做法的时间复杂度是 O ( n 2 ) O(n^2) O(n2)的,会超时。

所以当我们将祖宗节点从节点1换为另一个节点的时候,我们只能通过数学上的关系来计算出 g g g数组元素的值。这个也是换根DP的意义。

我们看下面的图:
在这里插入图片描述
红色框是非常好理解的,直接写成 f [ u ] [ k ] f[u][k] f[u][k]即可。上面的部分,我们可以写成 g [ f a ( u ) ] [ k − 1 ] g[fa(u)][k-1] g[fa(u)][k1]。因为到 u u u不超过 k k k的距离,即距离它的父亲节点不超过 k − 1 k-1 k1的距离。

但是这么写对吗?

答案是不对的, g [ f a ( u ) ] [ k − 1 ] g[fa(u)][k-1] g[fa(u)][k1] f [ u ] [ k ] f[u][k] f[u][k]是有重复部分的。我们需要减去这段重复的部分,那么关键问题是重复部分如何表示?

重复部分肯定是出现在了红色框中,红色框中到 f a ( u ) fa(u) fa(u)不超过距离 k − 1 k-1 k1,即距离 u u u不超过 k − 2 k-2 k2,同时重复部分又恰好是节点 u u u的子节点,所以这部分可以表示为: f [ u ] [ k − 2 ] f[u][k-2] f[u][k2]

所以最终的结果就是:

g [ u ] [ k ] = f [ u ] [ k ] + g [ f a ( u ) ] [ k − 1 ] − f [ u ] [ k − 2 ] g[u][k]=f[u][k]+g[fa(u)][k-1]-f[u][k-2] g[u][k]=f[u][k]+g[fa(u)][k1]f[u][k2]

但是上述方程成立的条件是 k ≥ 2 k\geq 2 k2的。

所以我们还得想一想 k ≤ 1 k \leq 1 k1的时候。

如果 k = 0 k=0 k=0 g [ u ] [ 0 ] g[u][0] g[u][0]其实就是 v a l [ u ] val[u] val[u],因为不超过距离 0 0 0的点只有本身。

如果 k = 1 k=1 k=1,那么 g [ u ] [ 1 ] g[u][1] g[u][1]其实就是 f [ u ] [ 1 ] + v a l [ f a ( u ) ] f[u][1]+val[fa(u)] f[u][1]+val[fa(u)],因为沿着父节点方向距离 u u u不超过 1 1 1的点,只有父节点,而树中,父节点是唯一的。沿着子节点方向,其实就是 u u u的各个子节点,而这些子节点可以统统用 f [ u ] [ 1 ] f[u][1] f[u][1]表示。

三、代码

#include<bits/stdc++.h>
#define endl '\n'
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 1e5 + 10;
vector<int>edge[N];
int f[N][25], g[N][25];
int val[N];
int n, k;

void dp(int u, int father)
{
	for(int i = 0; i <= k; i ++)
		f[u][i] = val[u];
	for(int i = 0; i < edge[u].size(); i ++ )
	{
		int son = edge[u][i];
		if(son == father)
			continue;
		dp(son, u);

		for(int j = 1; j <= k; j ++ )
		{
			f[u][j] += f[son][j - 1];
		}
	}
	return;
}

void dp2(int u, int father)
{
	for(int i = 0; i < edge[u].size(); i ++ )
	{
		int son = edge[u][i];
		if(son == father)
			continue;
		g[son][0] = val[son];
		g[son][1] = f[son][1] + val[u];
		for(int j = 2; j <= k; j ++ )
		{
			g[son][j] = g[u][j - 1] + f[son][j] - f[son][j - 2]; 
		}
		
		dp2(son, u);
	}
}

void solve()
{
	cin >> n >> k;
	for(int i = 0; i < n - 1; i ++ )
	{
		int a, b;
		cin >> a >> b;
		edge[a].push_back(b);
		edge[b].push_back(a);
	}

	for(int i = 1; i <= n; i ++ )
		cin >> val[i];

	dp(1, 0);
	for(int i = 0; i <= k; i ++ )
	{
		g[1][i] = f[1][i];
	}
	dp2(1, 0);
	// for(int i = 1; i <= n; i ++ )
	// {
	// 	cout << f[i][k] << endl;
	// }
	// cout << endl;
	for(int i = 1; i <= n; i ++ )
	{
		cout << g[i][k] << endl;
	}
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	solve();
}

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

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

相关文章

【数据结构初阶】单链表面试题|内含链表带环问题

目录 前言 链表面试题 1. 删除链表中等于给定值 val 的所有节点。oj链接 2.反转一个单链表。oj链接 3. 给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。oj链接 4. 输入一个链表&#xff0c;…

每天五分钟机器学习算法:贝叶斯算法中处理重复词语的三种方式

什么是重复词语? 我们预测一封邮件是否是垃圾邮件,前面已经介绍,我们需要对其进行分词处理,问题是分词处理之后很有可能有重复的词,那么这重复的词如何处理,这里我们介绍三种方式: 1.多项式模型 2.伯努利模型 3.混合模型 重复的情况举例 现在有一个垃圾邮件,它的内…

安装Linux虚拟机和Hadoop平台教程汇总及踩坑总结

&#x1f4cd;主要内容介绍安装Linux虚拟机、ubuntu系统、安装hadoop三个环节的教程链接介绍及本机与虚拟机的FTP传输教程总结&#xff08;直接找hadoop安装环节的5.filezilla传输文件&#xff09;新鲜出炉的踩坑总结和填坑指南安装Linux虚拟机和ubuntu系统一、材料和工具1、下…

站内SEO内容优化包括那些?

站内SEO优化是指优化网站内部结构&#xff0c;以提高搜索引擎对网站的识别和评价&#xff0c;从而提高网站在搜索引擎自然排名中的权重和位置。 站内SEO内容优化的目标是提高网站内容的质量和相关性&#xff0c;从而吸引更多的用户访问和留存。 以下是一些站内SEO优化的要点&…

Yolov5-交通标志检测与识别

项目介绍 上一篇文章介绍了基于卷积神经网络的交通标志分类识别Python交通标志识别基于卷积神经网络的保姆级教程&#xff08;Tensorflow&#xff09;&#xff0c;并且最后实现了一个pyqt5的GUI界面&#xff0c;并且还制作了一个简单的Falsk前端网页实现了前后端的一个简单交互…

C/C++内存管理讲解

c/C内存管理讲解 C/C内存分布 首先通过一些题目的引入讲解带大家走进C/C的内存分布。 eg1&#xff1a; 根据上述变量的定义&#xff0c;来判断它们所在的内存位置。 从接下来的4个选项中选出最佳答案填入&#xff08;注&#xff1a;可重复选&#xff09;。 A、栈 B、堆 C、数…

已知如下数据库表,写出查询各门课的分数最高者的SQL语句,要求格式为“科目,学生名,分数”,并按科目Id排序

题目描述 在某笔试题中遇到了这样的题目&#xff0c;之前学过数据库原理&#xff0c;但是这综合性太强&#xff0c;一下子犯了难。 解决过程 在数据库中建立上述表&#xff0c;以验证写的SQL对不对 平台&#xff1a;Navicate SQL 16 for MySQL 尝试写SQL查询 尝试1 …

CSS 扫盲

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录引入方式内部样式内联样式外部样式CSS 选择器CSS 常用属性值字体属性设置字体大小粗细文字样式文本属性文本颜色文本对齐文本装…

1640_MIT 6.828 fork函数的功能以及相关代码分析

全部学习汇总&#xff1a; GitHub - GreyZhang/g_unix: some basic learning about unix operating system. 继续分析之前看到的一段代码&#xff0c;先梳理一下这里遇到的fork函数的应用。 1. 这个是属于系统调用类的接口&#xff0c;也是这一段时间我看到的第一个这种类型的接…

Python3实现写作

导语T_T没有科研梦想的人半夜过来水篇文章~~~让Python学会写写歌&#xff0c;创创作~~~纯属娱乐~~~改编自PyTorch官网的一个教程&#xff0c;不过我用TF写的&#xff0c;然后生成英文变成了生成中文~~~Lets Go~~~相关文件百度网盘下载链接: https://pan.baidu.com/s/1VUEFR82Cq…

一个 适用 vue3 ts h5移动端 table组件

vue3-h5-table 介绍 适用于 vue3 ts 的 h5 移动端项目 table 组件 支持 左侧固定 滑动 每行点击回调 支持 指定列排序 链接 &#xff1a;https://github.com/duKD/vue3-h5-table 效果 props说明minTableHeight表格最小高度 可选 默认600rowNum表格显示几行 可选 默认 6he…

使用微软新必应(New Bing)AI机器人生成树莓派Pico W开发板MicroPython应用程序

微软新必应是一款由人工智能驱动的AI搜索引擎&#xff08;基于Chat GPT4.0的先进自然语言生成模型&#xff09;&#xff0c;它能与用户进行流畅、自然、有趣的对话&#xff0c;并提供可靠、及时的搜索结果&#xff0c;以及回答用户的各种问题。我们可以使用新必应生成程序代码、…

MySQL workbench基本查询语句

1.查询所有字段所有记录 SELECT * FROM world.city; select 表示查询&#xff1b;“*” 称为通配符&#xff0c;也称为“标配符”。表示将表中所有的字段都查询出来&#xff1b;from 表示从哪里查询&#xff1b;world.city 表示名为world的数据库中的city表&#xff1b; 上面…

13 node 程序后台执行加上 tail 命令, 中断 tail 命令, 同时也中断了 node 程序

前言 呵呵 最近帮朋友解决问题[2022.09.08] 需要启动一个 node 程序, 然后 需要一个 startUp.sh 脚本 然后 反手写了一个过去, 按道理 来说 应该是 后台启动了对应的 node 程序, 然后将 标准输出, 错误输出 输出到 logs/nohup.log 日志文件中, 然后基于 tail 命令 来查看 …

【Kafka】MM2同步Kafka集群时如何自定义复制策略(ReplicationPolicy)

文章目录需求准备工作自定义复制策略编译代码需求 使用MM2同步集群数据&#xff0c;topic名称不能变&#xff0c;默认的复制策略为&#xff1a;DefaultReplicationPolicy&#xff0c;这个策略会把同步至目标集群的topic都加上一个源集群别名的前缀&#xff0c;比如源集群别名为…

设计模式-第13章(状态模式)

状态模式状态模式状态模式的好处和用处工作状态状态模式 状态模式&#xff08;State&#xff09;&#xff0c;当一个对象的内在状态改变时允许改变其行为&#xff0c;这个对象看起来像是改变了其类。 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况…

【大数据】HDFS客户端命令行(hdfs dfs)详细使用说明

DFS命令使用概览使用说明lsdfducountappendToFilecatchecksumchgrpchmodchownconcatcopyFromLocalcopyToLocalcpcreateSnapshotdeleteSnapshotexpungefindgetgetfaclgetfattrgetmergeheadmkdirmoveFromLocalmoveToLocalmvputrenameSnapshotrmrmdirsetfaclsetfattrsetrepstattai…

实现VOC数据集与COCO数据集格式转换

实现VOC数据集与COCO数据集格式转换2、将voc数据集的xml转化为coco数据集的json格式2、COCO格式的json文件转化为VOC格式的xml文件3、将 txt 文件转换为 Pascal VOC 的 XML 格式<annotation><folder>文件夹目录</folder><filename>图片名.jpg</file…

2020蓝桥杯真题凯撒加密 C语言/C++

题目描述 给定一个单词&#xff0c;请使用凯撒密码将这个单词加密。 凯撒密码是一种替换加密的技术&#xff0c;单词中的所有字母都在字母表上向后偏移 3 位后被替换成密文。即 a 变为 d&#xff0c;b 变为 e&#xff0c;⋯&#xff0c;w 变为z&#xff0c;x 变为 a&#xff0…

【QT网络编程】实现UDP协议通信

文章目录概要&#xff1a;本期主要讲解QT中对UDP协议通信的实现。一、UDP协议通信二、Qt中UDP协议的处理1.QUdpSocket三、Qt实现UDP通信1.客户端2.服务器端结尾概要&#xff1a;本期主要讲解QT中对UDP协议通信的实现。 一、UDP协议通信 Internet 协议集支持一个无连接的传输协…