首页 > 代码库 > POJ1463 Strategic game (最小点覆盖 or 树dp)

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\n", 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 1354 0:(3) 1 2 355 1:(0) 56 2:(2) 4 557 3:(2) 6 758 4:(0) 59 5:(0) 60 6:(2) 8 961 7:(3) 10 11 1262 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\n", 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 1354 0:(3) 1 2 355 1:(0) 56 2:(2) 4 557 3:(2) 6 758 4:(0) 59 5:(0) 60 6:(2) 8 961 7:(3) 10 11 1262 8:(0) 63 9:(0) 64 10:(0) 65 11:(0) 66 12:(0) 67 */
View Code

 

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