P5521 题解
一道比较不错的思维题。
对于树上的每一个节点,我们考虑设节点 要放 朵梅花,如果从梅岭带出 朵梅花,就在节点 上放 朵梅花。
具体地,有以下两种情况:
第一种情况,梅花直接放所有子节点再放父节点。则易知 。
第二种情况,如果已经在节点 放了梅花,显然都会将其子节点的梅花收走。那么放一个子节点的花费为:
因为要放所有子节点,所以取其最大值。则有:
注意到 与子节点顺序有联系,那么就需要排序。
这里给出结论:直接按 从大到小排序。
证明:
设两个节点 , 相邻,且交换前的值是 ,交换后的值是 。
若满足条件 ,则有 。
因为 ,所以有:
显然原顺序优于交换顺序。
证毕。
至于时间复杂度的话,设树上每一个节点与 个节点相邻,则总的时间复杂度为 ,可以通过本题(或许可以钦定为 ?)。
#include <iostream>
#include <algorithm>
#include <vector>
#define MAXN 100005
using namespace std;
int n, p;
struct edge{int w, to, nxt;}e[MAXN << 1];
int head[MAXN], cnt = 1;
struct node{
int ans, w;
bool friend operator<(node a, node b){
return a.ans - a.w > b.ans - b.w;
};
}a[MAXN];
int read(){
int t = 1, x = 0;char ch = getchar();
while(!isdigit(ch)){if(ch == '-')t = -1;ch = getchar();}
while(isdigit(ch)){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
return x * t;
}
void write(int x){
if(x < 0){putchar('-');x = -x;}
if(x >= 10)write(x / 10);
putchar(x % 10 ^ 48);
}
void add(int u, int v, int w){
cnt++;e[cnt].to = v;e[cnt].nxt = head[u];head[u] = cnt;
}
void dfs(int now){
vector <node> tmp;tmp.clear();a[now].ans = a[now].w;
for(int i = head[now] ; i != 0 ; i = e[i].nxt){
int v = e[i].to;dfs(v);
tmp.push_back(a[v]);
a[now].ans += a[v].w;
}
sort(tmp.begin(), tmp.end());int tot = 0;
for(int i = 0 ; i < tmp.size() ; i ++){
a[now].ans = max(a[now].ans, tmp[i].ans + tot);
tot += tmp[i].w;
}
}
int main(){
n = read();
for(int i = 2 ; i <= n ; i ++)p = read(),add(p, i, 0);
for(int i = 1 ; i <= n ; i ++)a[i].w = read();
dfs(1);
for(int i = 1 ; i <= n ; i ++){
if(i != 1)putchar(' ');
write(a[i].ans);
}
putchar('\n');return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具