[USACO12FEB]附近的牛Nearby Cows
题目概述
题目描述
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.
给你一棵 \(n\) 个点的树,点带权,对于每个节点求出距离它不超过 \(k\) 的所有节点权值和 \(m_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-1\) 行,每行两个正整数 \(u,v\),表示 \(u,v\) 之间有一条边。
最后 \(n\) 行,每行一个非负整数 \(c_i\),表示点权。
输出格式
* Lines 1..N: Line i should contain the value of M(i).
输出 \(n\) 行,第 \(i\) 行一个整数表示 \(m_i\)。
输入输出样例
输入样例 #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\%\) 的数据:\(1 \le n \le 10^5\),\(1 \le k \le 20\),\(0 \le c_i \le 1000\)
解题报告
题意理解
给你一棵 \(n\) 个点的树,点带权,对于每个节点求出距离它不超过 \(k\) 的所有节点权值和 \(m_i\)。
算法解析
- 树形结构
- 统计一定距离的点权和
- 树上节点特别多,基本上要线性复杂度
- 程序员的第六感
综上所述,我们得知这道题目需要使用,树形DP算法。
然后我们不难设计出,状态表示
\[
f[i][j]表示,节点i的子树中,离它距离为j的奶牛总数
\]
因此,我们不难发现,在这个状态表示中,状态转移,只会从儿子节点中转移过来。
利用儿子节点,更新父亲节点。
\[
f[i][j]=\sum{f[k][j-1]} \\\\
k为i的儿子节点,j-1是因为儿子到父亲距离为1
\]
但是,题目并没有如此简单。
在本题中,对于一个树上节点,他可以被那些节点转移过来呢
- 子辈节点(儿子,子树,兄弟的子树)
- 同辈节点(兄弟)
- 祖辈节点(父亲,祖先)
对于,子辈,同辈,这些节点的转移,显然都是满足,树形DP的自下而上的转移方式。
但是,祖辈节点们,可就是完全违背,我们树形DP的转移方式。
怎么办?
我们不妨,再来一次转移,而且本次转移,自上而下
因此,我们利用父亲节点,更新儿子节点
\[
f[i][j]=\sum{f[S][j-1]} \\\\
s为i的父亲节点,同样j-1,是因为儿子到父亲距离为1
\]
那么这里的
\[
f[S][j-1]包含了哪些节点呢?
\]
我们根据这张图片,分析一波
父亲的转移,让我们的同辈节点,和同辈的儿子节点都累加了。
此时,我们发现
- 子辈节点,多。
- 同辈节点,刚好
- 父辈节点,刚好
我们发现,\(x\)的距离为\(2\)的点,包含到k距离为\(1\)的\(k\)的儿子们.
而这些点位于\(k\)的子树中的点已经在第一次转移,加入到里面去了。
因此,我们不得不,容斥原理,处理多余的子辈节点
推到出来,就是
\[
f[S][j]-f[x][j-2] \\\\
减去自己多余的子辈节点,S是x的父亲节点,y是x的儿子节点。 \\\\
j-1是S到x,(j-1)-1是S到y
\]
代码解析
#include <bits/stdc++.h>
using namespace std;
const int N=110000,K=21;
int n,k,a[N],f[N][K],deep[N];
vector<int> g[N];
void dfs(int x,int s)
{
deep[x]=deep[s]+1;
for(int y:g[x])
{
if (y==s)
continue;
dfs(y,x);
for(int p=1; p<=k; p++)
f[x][p]+=f[y][p-1];
}
}
void dfs2(int x)
{
for(int y:g[x])
{
if (deep[y]<=deep[x])
continue;
for(int p=k; p>=2; p--)
f[y][p]-=f[y][p-2];
for(int p=1; p<=k; p++)
f[y][p]+=f[x][p-1];
dfs2(y);
}
}
inline void init()
{
scanf("%d%d",&n,&k);
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);
}
for(int i=1; i<=n; i++)
scanf("%d",&f[i][0]);
dfs(1,0);
dfs2(1);
for(int i=1; i<=n; i++)
{
int ans=0;
for(int j=0; j<=k; j++)
ans+=f[i][j];
printf("%d\n",ans);
}
}
signed main()
{
init();
return 0;
}
原文地址:https://www.cnblogs.com/gzh-red/p/11844919.html
- Python基础知识梳理-第01部分
- 卷积神经网络之卷积操作
- Silverlight体积优化
- 江湖秘笈:说烦了破解、渗透等,不如大家一起聊聊硬盘加密?
- Nodejs学习笔记(十三)— PM2
- 十分钟带你了解服务化框架
- 十分钟带你了解服务化框架
- WCF技术剖析之十七:消息(Message)详解(上篇)
- 微信年底重磅更新,这次小程序才是重头戏!
- 《EnterLib PIAB深入剖析》系列博文汇总
- Nodejs学习笔记(八)--- Node.js + Express 实现上传文件功能(felixge/node-formidable)
- 大牛教你使用7种卷积神经网络进行物体检测!
- Enterprise Library深入解析与灵活应用(3):倘若将Unity、PIAB、Exception Handling引入MVP模式.. .. ..
- 别对我说谎!你的小九九我都知道
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- numpy/pandas瞎搞系列(一):OLS,WLS的numpy实现
- redis实战第三篇 redis sentinel安装和部署
- 后浪,谈谈你对jvm性能调优的理解
- Homer预测共表达基因的motif
- redis实战第一篇 安装和使用
- lombok在java项目中的使用
- MySQL 的全文索引.
- Swift Reusable开源库使用
- 面试官:聊聊你读过的开源代码中用到的设计模式
- Swift Moya的简单使用
- 信用风险建模 in Python 系列 5 - 阈值模型概述
- 理解 Kubernetes 的亲和性调度
- CppSQLite - C++ Wrapper for SQLite
- 在.NET Core中使用MongoDB明细教程(3):Skip, Sort, Limit, Projections
- wsl 2 unbuntu 部署 asp.net core 使用 nginx 做反向代理,调试文件上传失败