【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
",min(f[0][1],f[0][0]));
42     }
43     return 0;
44 }
AC Code1
原文地址:https://www.cnblogs.com/shl-blog/p/10772809.html