要记录三种状态:
1、被子节点覆盖
2、等待父节点覆盖
3、建立覆盖节点
然后转移就好了,有一点麻烦的就是被子节点覆盖,需要保证至少有一个子节点建立
注:检查变量名与实际含义。
码:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int f[1505][4],k[1505],o,m,n,i,j,x,fu[1505];
vector<int>v[1505];
void dfs(int o)
{
int i,nd,min1=999999999,min2=0;
f[o][1]=k[o];
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
dfs(nd);
f[o][1]+=min(f[nd][0],min(f[nd][1],f[nd][2]));//建在这里
if(f[nd][1]-f[nd][2]<min1)min1=f[nd][1]-f[nd][2],min2=nd; //影响到这里
f[o][0]+=min(f[nd][2],f[nd][1]);//
}
if(v[o].size()==0)
{
f[o][2]=999999999;
return ;
}
f[o][2]+=f[min2][1];
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
if(nd==min2)continue;
f[o][2]+=min(f[nd][1],f[nd][2]);
}
}
int main()
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&o,&x,&m);
k[o]=x;
for(j=1;j<=m;j++)
{
scanf("%d",&x);
v[o].push_back(x);
fu[x]=o;
}
}
for(i=1;i<=n;i++)
if(fu[i]==0)
{
o=i;
break;
}
dfs(o);
printf("%d",min(f[o][1],f[o][2]));
}