标签:roo 最小 def ace print 判断 它的 更新 efi
一道还算比较好写的“求树的最大独立集”的问题。
f [ x ] [ 0 ] 表示以x为节点的子树上,在x位置不放士兵时,士兵数量的最小值;
f [ x ] [ 1 ] 表示以x为节点的子树上,在x位置要放士兵时,士兵数量的最小值;
那么方程就写出来了,在回溯的时候,对于f [ x ] [ 0 ] ,它的子节点一定都要放,累加f [ x ] [ 1 ] ;那么对于f [ x ] [ 1 ] ,取最小值就可以了。
注意边界判断,当你到树的叶子的时候,要在操作 f 之后返回。
代码如下:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; #define maxn 2000 struct data { int num,child[maxn]; } node[maxn]; int f[maxn][3],n,root; bool vis[maxn]; void dp(int x) { f[x][0]=0; f[x][1]=1; if(!node[x].num) return ; for(int i=1;i<=node[x].num;i++) { dp(node[x].child[i]); f[x][0]+=f[node[x].child[i]][1]; f[x][1]+=min(f[node[x].child[i]][1],f[node[x].child[i]][0]); } } int main() { memset(f,0x3f,sizeof(f)); scanf("%d",&n); for(int i=1;i<=n;i++) { int x,y; scanf("%d",&x); scanf("%d",&node[x].num); for(int j=1;j<=node[x].num;j++) { scanf("%d",&node[x].child[j]); vis[j]=1; } } while(vis[root]) root++; dp(root); printf("%d",min(f[root][0],f[root][1])); return 0; }
最后想加一句,所谓树形dp,我认为就是想方设法利用刚刚到过(并从那里回来)的点更新现在这个点,更新到最后就是答案了。
标签:roo 最小 def ace print 判断 它的 更新 efi
原文地址:https://www.cnblogs.com/popo-black-cat/p/10182644.html