[USACO12FEB Gold]Nearby Cows 题解报告
[USACO12FEB Gold]Nearby Cows
问题描述
给你一棵 个点的树,点带权,对于每个节点求出距离它不超过 的所有节点权值和 。
输入格式
第一行两个正整数,。
接下来 行,每行两个正整数 ,,表示, 之间有一条边。
最后 行,每行一个非负整数 ,表示点权。
输出格式
输出 行,第 行一个整数表示 。
样例输入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
数据范围
对于%的数据:
求距离它不超过k的所有节点权值的和
首先想的是一个一个枚举
不知道数据允许不
啊,不可以(ˉ▽ˉ;)...
所以,我们来想一想另外的方法
???
万能的DP出场了!!!
我们可以尝试
设表示从点开始向下内权值之和
代表从点开始距离的权值之和
可以很容易算出来
对于一个点u,
而也可以得出,
这个方程式说父亲的信息+u向下的信息-无用信息
这里无用的信息就是
因为父亲的信息包括了从父亲往下的信息
而对于来说,父亲往下的点距离ta并没有的距离
只有的距离
所以需要将父亲往下的答案减去
所以就是往上的权值之和
最后输出就行了
code
#include<bits/stdc++.h>
using namespace std;
const int N=100002;
int n,k,cnt=0,x,y;
int hd[N],c[N],d[N][22],f[N][22];
struct Node {
int nxt,to;
} tr[N*2];
void dfs(int x,int fa,int u) {
d[x][u]+=c[x];
for(int i=hd[x]; i; i=tr[i].nxt) {
if(tr[i].to==fa) continue;
d[x][u]+=d[tr[i].to][u-1];
dfs(tr[i].to,x,u);
}
}
void dfsb(int x,int fa,int u) {
int w;
if(u>=2) w=d[x][u-2];
else w=0;
f[x][u]=f[fa][u-1]-w+d[x][u];
for(int i=hd[x]; i; i=tr[i].nxt){
if(tr[i].to!=fa){
dfsb(tr[i].to,x,u);
}
}
}
void add(int x,int y) {
tr[++cnt].nxt=hd[x];
tr[cnt].to=y;
hd[x]=cnt;
}
int main() {
scanf("%d%d",&n,&k);
for(int i=1; i<n; i++) {
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1; i<=n; i++) {
scanf("%d",&c[i]);
d[i][0]=f[i][0]=c[i];
}
if(!k) {
for(int i=1; i<=n; i++) {
printf("%d\n",c[i]);
}
return 0;
}
for(int i=1; i<=k; i++) {
dfs(1,0,i);
f[1][i]=d[1][i];
}
for(int i=1; i<=k; i++) {
for(int j=hd[1];j;j=tr[j].nxt){
dfsb(tr[j].to,1,i);
}
}
for(int i=1; i<=n; i++) {
printf("%d\n",f[i][k]);
}
return 0;
}
完结撒花❀
★,°:.☆( ̄▽ ̄)/$:.°★ 。
本文作者:Yvette的博客
本文链接:https://www.cnblogs.com/yvette1217/p/16348976.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步