P4657 [CEOI2017]Chase
不得不说这个树形dp做法真牛
题目大意:给出一棵树,求一条路径,选择路上的V个点,使得被选择的点的相邻且不在路径上的点的权值和最大。
考虑换根的话很麻烦 还是类似毛毛虫那个题 每个点一定是处于一个路径的中间的 可能是一上一下 一下一上 一下 一上这四种情况
因为这个题目是有方向性的 a->b 的权值和 是不等于b->a 的 所以次大最大的方案也不是很好做 这个题解法的灵魂就是去重的操作
设b[x][i] 表示从x向x的子树走取i个点的最大权值和
设c[x][i] 表示从x的子树走到x取i个点的最大权值和
设g[x]表示x周围的点的权值和
设f[x]表示x点的权值
转移方程:
b[u][i]=max(b[u][i],b[v][tot-i]+g[u]-f[fa])
c[u][i]=max(c[u][i],c[v][tot-i]+g[u]-f[v])
答案:ans=max(ans,c[u][i]+b[v][tot-i],c[u][tot],b[u][tot])
设当前节点为x,y1,y2,y3...为x的儿子
为了避免重复走相同的路径 我们在不断在y跟新x之前就先统计答案
比如我们先跟新了y1和y2 此时在加入y3之前就跟新ans
我们用的是y1和y2跟新的c[][] 和y3的b[][]跟新的答案 所以c里面一定不包含y3
这个题的解决办法真的好优美
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=1e5+5;
int N,V,x,y,tot,top,F[maxn],sta[maxn];
int son[maxn<<1],nxt[maxn<<1],lnk[maxn];
long long g[maxn],c[maxn][105],b[maxn][105],ans;
inline int read() {
int ret=0,f=1,ch=getchar();
for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
return ret*f;
}
inline void add_edge(int x,int y) {
son[++tot]=y,nxt[tot]=lnk[x],lnk[x]=tot;
son[++tot]=x,nxt[tot]=lnk[y],lnk[y]=tot;
}
inline void DP(int x,int y,int f) {
// ans一定要在前面赋值,这样可以避免从y走到x又走回y
for (int i=1; i<=V; ++i) ans=max(ans,c[x][i]+b[y][V-i]);
for (int i=1; i<=V; ++i)
c[x][i]=max(c[x][i],max(c[y][i],c[y][i-1]+g[x]-F[y])),
b[x][i]=max(b[x][i],max(b[y][i],b[y][i-1]+g[x]-F[f]));
}
void dfs(int x,int pre) {
for (int i=1; i<=V; ++i) c[x][i]=g[x],b[x][i]=g[x]-F[pre];
for (int k=lnk[x]; k; k=nxt[k]) if (son[k]^pre) dfs(son[k],x),DP(x,son[k],pre);
// 对于节点x,y和z是它的子节点并且,y先于z遍历。
// 上面的方法,无法计算z->x->y所以要倒着做一遍
for (int i=1; i<=V; ++i) c[x][i]=g[x],b[x][i]=g[x]-F[pre];
top=0;for (int k=lnk[x]; k; k=nxt[k]) if (son[k]^pre) sta[++top]=son[k];
for (int i=top; i; --i) DP(x,sta[i],pre);
ans=max(ans,max(c[x][V],b[x][V]));
}
int main() {
N=read(),V=read();
for (int i=1; i<=N; ++i) F[i]=read();
for (int i=1; i<N; ++i) add_edge(x=read(),y=read()),g[x]+=F[y],g[y]+=F[x];
return dfs(1,0),printf("%lld",ans),0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?