链接:
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 }
时间: 2024-10-25 09:32:40