一棵有点权的树,选择一些点,
使得每个点至少满足下列中的一个: 1.已被选择 2.父亲被选择 3.子节点至少有一个被选择
求点权和最小值
f[x][0]=SUM{ min(f[y][1],f[y][2] }
f[x][2] = SUM { min(f[y][0],f[y][1],f[y][2]) } +a[I]
f[x][1] = min{ s-min(f[y][1],f[y][2]) + f[y][2] },s=sum{min(f[y][1],f[y][2] } // 先假设子节点一个不选,求出s ,现在选择y ,即取 f[y][2],
从s里去掉y的min() 值,改为f[y][2]
#include <bits/stdc++.h> using namespace std ; const int N=1999; int a[N],in[N],f[N][3]; int all,go[N],nxt[N],hd[N],n; void add(int x,int y){ go[++all]=y,nxt[all]=hd[x],hd[x]=all; } void dfs(int x){ int i,s=0; f[x][2]=a[x]; for(i=hd[x];i;i=nxt[i]){ int y=go[i]; dfs(y); f[x][0]+=min(f[y][1],f[y][2]); f[x][2]+=min(f[y][0],min(f[y][1],f[y][2])); s+=min(f[y][1],f[y][2]); } f[x][1]=1e9; for(i=hd[x];i;i=nxt[i]){ int y=go[i]; f[x][1]=min(f[x][1],s-min(f[y][1],f[y][2])+f[y][2]); } } int main(){ int rt,i,x,y,T; cin>>n; for(i=1;i<=n;i++){ cin>>x; cin>>a[x]>>T; while(T--) cin>>y,in[y]++,add(x,y); } for(rt=1;in[rt];) rt++; dfs(rt); cout<<min(f[rt][1],f[rt][2]); }