传送门
作为(HNOI2018)最简单的题,这个题确实不算难
虽然我一开始也没想出满分
看了眼题解,考虑到了倒推,这题差不多就没了
当走到叶子节点的时候考虑一下选了多少条公路翻修和多少条铁路翻修
对于非叶子节点就枚举翻修哪条边,转移就好了
一个小插曲:
本来写的记搜,由于看错题了,以为自己写错了,全删了,才学的题解的(dp)写法
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void read(int &x)
{
char ch;bool ok;
for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
#define rg register
const int maxn=4e4+10;
int n,l[maxn],r[maxn],cnt;
long long f[maxn][40][40];
struct oo{int a,b,c;}d[maxn];
void dfs(int x,int a,int b)
{
if(!l[x]&&!r[x]){
for(rg int i=0;i<=a;i++)
for(rg int j=0;j<=b;j++)
f[x][i][j]=1ll*d[x].c*(d[x].a+i)*(d[x].b+j);
return ;
}
dfs(l[x],a+1,b),dfs(r[x],a,b+1);
for(rg int i=0;i<=a;i++)
for(rg int j=0;j<=b;j++)
f[x][i][j]=min(f[l[x]][i+1][j]+f[r[x]][i][j],f[l[x]][i][j]+f[r[x]][i][j+1]);
}
int main()
{
read(n);
for(rg int i=1,x,y;i<n;i++){
read(x),read(y);
if(x>0)l[i]=x;else l[i]=n-x;
if(y>0)r[i]=y;else r[i]=n-y;
}
for(rg int i=1;i<=n;i++)read(d[i+n].a),read(d[i+n].b),read(d[i+n].c);
dfs(1,0,0);
printf("%lld
",f[1][0][0]);
}