POJ 1463 树型DP

链接:

http://poj.org/problem?id=1463

题意:

求一棵树的最小点覆盖

题解:

dp[i][0]、dp[i][1]分别表示不在i结点上和在i结点上放置士兵时整个以i结点为根的子树被覆盖用到用到目标的最少数量

状态转移:

对叶子结点,有dp[i][0]=0,dp[i][1]=1  (也是递归的出口)

对非叶子结点,有

dp[i][0]=∑(dp[i][1])

dp[i][1]=∑(min(dp[j][0],dp[j][1]))+1  (j为i的子结点)

代码:

31 int a[MAXN];
32 int dp[MAXN][2];
33 VI G[MAXN];
34 
35 void DP(int u) {
36     int dp0 = 0, dp1 = 0;
37     if (G[u].size() == 0) {
38         dp[u][1] = 1;
39         dp[u][0] = 0;
40         return;
41     }
42     rep(i, 0, G[u].size()) {
43         int v = G[u][i];
44         DP(v);
45         dp1 += min(dp[v][1], dp[v][0]);
46         dp0 += dp[v][1];
47     }
48     dp[u][1] = dp1 + 1;
49     dp[u][0] = dp0;
50 }
51 
52 int main() {
53     int n;
54     while (cin >> n) {
55         memset(dp, 0, sizeof(dp));
56         rep(i, 0, MAXN) G[i].clear();
57         int root = -1;
58         rep(i, 0, n) {
59             int u, m;
60             scanf("%d:(%d)", &u, &m);
61             if (root == -1) root = u;
62             while (m--) {
63                 int v;
64                 scanf("%d", &v);
65                 G[u].pb(v);
66                 if (v == root) root = u;
67             }
68         }
69         DP(root);
70         cout << min(dp[root][0], dp[root][1]) << endl;
71     }
72     return 0;
73 }
原文地址:https://www.cnblogs.com/baocong/p/6763832.html