【POJ1463】Strategic game
这是一道树形dp的基本模型——树的最大独立集问题。
这种基本模型的解法是这样的:定义f[i][1/0]表示在以i为根的子树中,i选/不选的最小代价是多少,那么答案是min(f[0][1],f[0][0])。
考虑状态转移,对于i的每一个儿子j,若i选择,那么j可选可不选,如果i不选,那么j一定选。
也就是说
f[i][1]=∑min(f[j][1],f[j][0]),j∈son(i)
f[i][0]=∑f[j][1],j∈son(i)
这样我们对一棵树进行一次深度优先遍历,遍历的同时即可完成dp
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 struct node { 7 int next,to; 8 }a[3010]; 9 int num,head[3010]; 10 int n; 11 int f[1510][3]; 12 inline void add(int from,int to) { 13 a[++num].next=head[from]; 14 a[num].to=to; 15 head[from]=num; 16 } 17 void dfs(int u,int fa) { 18 f[u][1]=1; 19 f[u][0]=0; 20 for(int i=head[u];i;i=a[i].next) { 21 int v=a[i].to; 22 if(v==fa) continue ; 23 dfs(v,u); 24 f[u][1]+=min(f[v][1],f[v][0]); 25 f[u][0]+=f[v][1]; 26 } 27 } 28 int main() { 29 while(scanf("%d",&n)) { 30 memset(f,0,sizeof(f)); 31 num=0; 32 for(int i=1,x,j;i<=n;i++) { 33 scanf("%d:(%d)",&x,&j); 34 for(int k=1,q;k<=j;k++) { 35 scanf("%d",&q); 36 add(x,q); 37 add(q,x); 38 } 39 } 40 dfs(0,-1); 41 printf("%d\n",min(f[0][1],f[0][0])); 42 } 43 return 0; 44 }