洛谷2458
f[now][0]表示以当前点为根,且要取该点,满足条件的最小
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> using namespace std; int head[1501],to[1501],nex[1501],val[1501],indg[1501],f[1501][3],n,cnt,rt; inline void read(int &x){ char ch=getchar();x=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} } void addedge(int u,int v){ to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt; } void dfs(int now){ if(!head[now]){f[now][0]=f[now][1]=val[now];f[now][2]=0;return;} f[now][0]=val[now];f[now][2]=0; for(int i=head[now];i;i=nex[i]){ dfs(to[i]); f[now][0]+=min(f[to[i]][1],min(f[to[i]][2],f[to[i]][0])); f[now][2]+=min(f[to[i]][0],f[to[i]][1]);} f[now][1]=1e9; for(int i=head[now];i;i=nex[i]){ f[now][1]=min(f[now][1],f[now][2]-min(f[to[i]][0],f[to[i]][1])+f[to[i]][0]); } } int main(){ read(n); for(int i=1;i<=n;i++){ int u,som,v;read(u);read(val[u]);read(som); while(som--){read(v);indg[v]++;addedge(u,v);} } for(int i=1;i<=n;i++)if(!indg[i]){rt=i;break;} dfs(rt); printf("%d",min(f[rt][0],f[rt][1])); }
f[now][1]表示以当前点为根,至少取它的一个儿子,满足条件的最小值
f[now][2]表示他的儿子均被覆盖,满足条件的最小值
f[now][0]=val[now]+segma(min(f[son][0~2]));
f[now][1]=min(f[now][2]-min(f[son][0~1])+f[son][0])
f[now][2]=segma(f[son][0~1])
再注意叶子节点的赋值即可