[IOI2005]Riv 河流
XL.[IOI2005]Riv 河流
新转移方式get~~~
我必须吐槽一下现在赞最多的那篇题解,虽然思路巧妙,但是明显没有“物尽其用”,对于各DP数组的真实含义也没有把握清楚。
一个naive的想法就是:设表示:在的子树中,修了个场子,的最小费用。
但是这样不是很好转移——子树传上来的信息不能直接合并,因为我们必须知道场子到底修哪了才能准确得出答案。
而我们又不可能在状态里面维护这么多场子——状压不了。
等等,我们为什么要从根记录子树,为什么不是从子树记录根?
我们设表示:
以为根的子树中,修了个堡。并且,强制在第个点修个堡(是的祖先)。
这样,合并子树时就可以直接背包了——因为每个节点流到的堡确定了,代价自然就可以提前算出。
即:
每次将的状态同合并。
但这样就会出现一些问题——我们说要在修个堡,但是这只是空头支票,没有算到里面,当访问到时,这个债是要还的!
因此对于,我们应该让全体右移一位,即,且(欠的一个堡还不回来,只能破产)。
还有,我们要计算位置新产生的代价。这个代价要么位置额外再修一个堡,要么就是到的距离。因此我们有
则答案为(号点有个免费的堡)。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,head[110],cnt,f[110][110][60],g[60],val[110],dis[110],anc[110],tp;
struct node{
int to,next,val;
}edge[210];
void ae(int u,int v,int w){
edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
}
void dfs(int x){
anc[++tp]=x;
for(int i=head[x],y;i!=-1;i=edge[i].next){
y=edge[i].to,dis[y]=dis[x]+edge[i].val,dfs(y);
for(int j=1;j<=tp;j++){
for(int k=0;k<=m;k++)g[k]=0x3f3f3f3f;
for(int k=0;k<=m;k++)for(int l=0;l<=k;l++)g[k]=min(g[k],f[x][anc[j]][k-l]+f[y][anc[j]][l]);
for(int k=0;k<=m;k++)f[x][anc[j]][k]=g[k];
}
}
for(int j=m;j;j--)f[x][x][j]=f[x][x][j-1];
f[x][x][0]=0x3f3f3f3f;
for(int j=1;j<tp;j++)for(int k=0;k<=m;k++)f[x][anc[j]][k]+=val[x]*(dis[x]-dis[anc[j]]),f[x][anc[j]][k]=min(f[x][anc[j]][k],f[x][x][k]);
tp--;
}
int main(){
scanf("%d%d",&n,&m),m++,memset(head,-1,sizeof(head));
for(int i=1,x,y;i<=n;i++)scanf("%d%d%d",&val[i],&x,&y),ae(x,i,y);
dfs(0);
// for(int i=1;i<=n;i++)printf("%d ",dis[i]*val[i]);puts("");
printf("%d\n",f[0][0][m]);
return 0;
}
分类:
DP
, DP——背包/树上背包
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!