首页 > 其他分享 >【LuoGu】3047 Nearby Cows G ——两次DFS+树上DP

【LuoGu】3047 Nearby Cows G ——两次DFS+树上DP

时间:2023-09-10 21:12:33浏览次数:36  
标签:le int LuoGu DFS fa 权值 节点 DP

[USACO12FEB] Nearby Cows G

题目描述

给你一棵 \(n\) 个点的树,点带权,对于每个节点求出距离它不超过 \(k\) 的所有节点权值和 \(m_i\)。

输入格式

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

输出格式

输出 \(n\) 行,第 \(i\) 行一个整数表示 \(m_i\)。

样例 #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

【数据范围】
对于 \(100\%\) 的数据:\(1 \le n \le 10^5\),\(1 \le k \le 20\),\(0 \le c_i \le 1000\)

解决方案

树上DP+两次DFS

首先对于某一个结点\(u\),考虑答案的组成部分:
1、\(u\)的子树中距离不超过\(k\)的所有点的权值和;
2、不在\(u\)的子树中的距离不超过\(k\)的所有点的权值和;

第一部分用一个简单的树形\(DP\)(第一次\(DFS\))即可:设\(f[i][j]\)表示以\(i\)为根的子树中距离为\(j\)的所有节点的权值和。则\(f[i][j]\)就等于距离\(i\)的所有子结点距离不超过\(j-1\)的权值和,即状态转移方程为$$f[i][j] = \sum f[k][j-1]$$,其中\(k \in i\)的子节点。
经过第一次\(DFS\)后,我们就求出了对于每一个节点\(i\),其子树中所有满足要求的答案。然而题目的要求不止子树,因此还需要对非\(i\)的子树中的节点。
设\(i\)的父节点是\(fa\),\(d[i][j]\)表示距离节点\(i\)距离为\(j\)的所有节点的权值和。首先初始化\(d[i][j] == f[i][j]\),然后\(d[i][j] += d[fa][j - 1]\)。但是这样会有重复,因为距离\(fa\)距离为\(j-1\)的点在第一次算子树距离为\(j-2\)的答案部分中已经算过一次,这里会重复计算。因此\(d[i][j]\)需要再减去\(f[i][j-2]\)。状态转移方程为$$d[i][j] = \sum d[fa][j-1] - f[i][j-2]$$在实际实现时,\(d\)和\(f\)数组可以用同一个,但是在第二次\(DFS\)进行容斥时需要倒序遍历(用到上一个时刻的状态量)。

#include<bits/stdc++.h>

const int N = 100010;

int n, k;
std::vector<std::vector<int>> g(N);
int c[N];
int f[N][25];

void dfs1(int u, int fa){
	for(auto v:g[u]){
		if(v == fa) continue;
		dfs1(v, u);
		for(int j = 1; j <= k; j ++ ){
			f[u][j] += f[v][j - 1];
		}
	}
}

void dfs2(int u, int fa){
	for(auto v:g[u]){
		if(v == fa) continue;
		for(int j = k; j >= 2; j -- ) f[v][j] -= f[v][j - 2];   //倒序遍历,类似于01背包
		for(int j = 1; j <= k; j ++ ) f[v][j] += f[u][j - 1];
		dfs2(v, u);
	}
}

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

	std::cin >> n >> k;
	for(int i = 0; i < n - 1; i ++ ){
		int u, v;
		std::cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}

	for(int i = 1; i <= n; i ++ ){
		std::cin >> c[i];
		f[i][0] = c[i];
	}

	dfs1(1, 0);
	dfs2(1, 0);

	for(int i = 1; i <= n; i ++ ){
		int ans = 0;
		for(int j = 0; j <= k; j ++ ){
			ans += f[i][j];
		}
		std::cout << ans << '\n';
	}

	return 0;
}

标签:le,int,LuoGu,DFS,fa,权值,节点,DP
From: https://www.cnblogs.com/yjx-7355608/p/17691923.html

相关文章

  • hdfs批量上传下载文件和删除指定目录下文件
    hdfs批量上传下载文件和删除指定目录下文件一、hdfs批量下载文件hdfsdfs-gets3a://bigdata/infra/zeppelin/notebook/二、hdfs批量上传文件hdfsdfs-put./*/bigdata/infr/zeppelin/notebook/三、hdfs删除指定目录hdfsdfs-rm-r/bigdata/infra/zeppelin/notebook/wei.ji10......
  • 线性DP
    DP三要素:状态,阶段,决策(转移)阶段:第i层状态:目前情况写代码三要素:边界、目标、转移DP要求:无后效性Mr.Young'sPicturePermutations要求从左到右和从上到下都递减首先肯定按顺序加入从左到右很明确,加到最右边从上到下怎么维护?其实就是这一行加完之后不超过上一行就行发现......
  • 【LuoGu】2014 选课——树上DP
    [CTSC1997]选课题目描述在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有\(N\)门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有......
  • 什么是 SAP ABAP AMDP?
    SAPAMDP(ABAPManagedDatabaseProcedure)是SAP的一项先进技术,用于在SAPHANA数据库上执行高性能的数据库操作。它允许ABAP开发人员编写数据库过程,这些过程可以在数据库级别上执行,从而实现更快的数据处理和更高的性能。在本文中,我将详细解释SAPAMDP的概念、工作原理以及如何在ABA......
  • 10 UDP 聊天实现
    packageInternet;importjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetSocketAddress;//UDP实现聊天,两边都是发信方,也是收信方publicclassTest10_UDP_Me{pub......
  • 9 UDP 消息发送
    没有客户端和服务端这一说法packageInternet;importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetAddress;importjava.net.SocketException;//UDP:类似发短信//发送端publicclassTest09_UDP_User1{publicstaticvoidma......
  • Ubuntu通过终端命令下载时提示“dpkg --configure -a......"
    如果之前在下载东西时,中途取消或中断可能会出现这种情况。结果 解决办法:在终端输入sudodpkg--configure-a ......
  • UDP协议&&UDP广播通信
    UDP协议概念传输层主要的应用协议模型有,TCP,UDP两种。TCP协议占主导地位,绝大多数网络都是借助TCP协议完成数据传输,但UDP也是不了或缺的重要通信手段相较于TCP,UDP通信形式像发短信。不需要建立连接。只需要专心获取数据就可以,省去了三次握手,通信速度可以大大提高,伴随着通信的稳......
  • 状态压缩dp
    蒙德里安的梦想问题描述问题分析$f[i][j]=\displaystyle\sum_{0到1<<n-1中所有合法的k}(f[i-1][k])$$f[m][0]$的含义为前$m-1$列摆好,且从第$m-1$列伸出到第m列状态为$0$的方案数,显然这就是答案(原因见下图)$k$是否合法需要看$k$和$j$的关系,第一个条件表示第$i-2$列......
  • luogu P1419 题解
    题目链接description给定一个长度为\(n\)的序列(值域为\([-10^4,10^4]\))和正整数\(st,ed\)。求一个区间,使得其长度\(\in[st,ed]\)且平均值最大,输出平均值。\(1\leqn\leq10^5\)solution这里给出一个复杂度线性的做法。求出前缀和数组\(s\),答案相当于\(\max\limit......