POJ1463 Strategic game (最小点覆盖 or 树dp)

题目链接:http://poj.org/problem?id=1463

给你一棵树形图,问最少多少个点覆盖所有的边。

可以用树形dp做,任选一点,自底向上回溯更新。

dp[i][0] 表示不选i点 覆盖子树所有边的最少点个数,那选i点的话,那么i的邻接节点都是必选的,所以dp[i][0] += dp[i.son][1]

dp[i][1] 表示选i点 覆盖子树所有边的最少点个数,那么i的邻接点可选可不选(而不是一定不选,看注释样例就知道了),所以dp[i][0] += min(dp[i.son][1], dp[i.son][0])

 1 //dp
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef long long LL;
15 typedef pair <int, int> P;
16 const int N = 1505;
17 vector <int> G[N];
18 int dp[N][2];
19 
20 void dfs(int u, int p) {
21     dp[u][0] = 0, dp[u][1] = 1;
22     for(int i = 0; i < G[u].size(); ++i) {
23         int v = G[u][i];
24         if(v == p)
25             continue;
26         dfs(v, u);
27         dp[u][0] += dp[v][1];
28         dp[u][1] += min(dp[v][0], dp[v][1]);
29     }
30 }
31 
32 int main()
33 {
34     int n;
35     while(~scanf("%d", &n)) {
36         int u, num, v;
37         for(int i = 1; i <= n; ++i) {
38             scanf("%d:(%d)", &u, &num);
39             while(num--) {
40                 scanf("%d", &v);
41                 G[u].push_back(v);
42                 G[v].push_back(u);
43             }
44         }
45         dfs(0, -1);
46         printf("%d
", min(dp[0][0], dp[0][1]));
47         for(int i = 0; i < n; ++i)
48             G[i].clear();
49     }
50     return 0;
51 }
52 /*
53 13
54 0:(3) 1 2 3
55 1:(0) 
56 2:(2) 4 5
57 3:(2) 6 7
58 4:(0) 
59 5:(0) 
60 6:(2) 8 9
61 7:(3) 10 11 12
62 8:(0) 
63 9:(0) 
64 10:(0) 
65 11:(0) 
66 12:(0) 
67 */
View Code

边完全覆盖,也就是最小点覆盖所有边。

二分图中最大匹配=最小点覆盖

 1 //dp
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef long long LL;
15 typedef pair <int, int> P;
16 const int N = 1505;
17 vector <int> G[N];
18 int dp[N][2];
19 
20 void dfs(int u, int p) {
21     dp[u][0] = 0, dp[u][1] = 1;
22     for(int i = 0; i < G[u].size(); ++i) {
23         int v = G[u][i];
24         if(v == p)
25             continue;
26         dfs(v, u);
27         dp[u][0] += dp[v][1];
28         dp[u][1] += min(dp[v][0], dp[v][1]);
29     }
30 }
31 
32 int main()
33 {
34     int n;
35     while(~scanf("%d", &n)) {
36         int u, num, v;
37         for(int i = 1; i <= n; ++i) {
38             scanf("%d:(%d)", &u, &num);
39             while(num--) {
40                 scanf("%d", &v);
41                 G[u].push_back(v);
42                 G[v].push_back(u);
43             }
44         }
45         dfs(0, -1);
46         printf("%d
", min(dp[0][0], dp[0][1]));
47         for(int i = 0; i < n; ++i)
48             G[i].clear();
49     }
50     return 0;
51 }
52 /*
53 13
54 0:(3) 1 2 3
55 1:(0) 
56 2:(2) 4 5
57 3:(2) 6 7
58 4:(0) 
59 5:(0) 
60 6:(2) 8 9
61 7:(3) 10 11 12
62 8:(0) 
63 9:(0) 
64 10:(0) 
65 11:(0) 
66 12:(0) 
67 */
View Code
原文地址:https://www.cnblogs.com/Recoder/p/5830986.html