POJ 3659 Cell Phone Network (树dp)

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

给你一个树形图,一个点可以覆盖他周围连接的点,让你用最少的点覆盖所有的点。

dp[i][0]表示用i点来覆盖,dp[i][1]表示用孩子节点来覆盖,dp[i][2]表示用父节点来覆盖

(1) dp[i][0] = min(dp[i.son][0], dp[i.son][1], dp[i.son][2])

(2) dp[i][1] = min(dp[i.son][0], dp[i.son][1]) //特判

(3) dp[i][2] = min(dp[i.son][0], dp[i.son][1])

注意(2)的情况,因为i需要被覆盖,所以dp[i.son][0]至少需要取到一个。

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 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 = 1e4 + 5;
17 int dp[N][3];
18 struct Edge {
19     int next, to;
20 }edge[N << 1];
21 int head[N], cnt;
22 
23 inline void add(int u, int v) {
24     edge[cnt].next = head[u];
25     edge[cnt].to = v;
26     head[u] = cnt++;
27 }
28 
29 void dfs(int u, int p) {
30     dp[u][0] = 1, dp[u][1] = dp[u][2] = 0;
31     bool flag = false;
32     int Min = 10000;
33     for(int i = head[u]; ~i; i = edge[i].next) {
34         int v = edge[i].to;
35         if(v == p)
36             continue;
37         dfs(v, u);
38         dp[u][0] += min(dp[v][0], min(dp[v][1], dp[v][2]));
39         dp[u][2] += min(dp[v][1], dp[u][0]);
40         if(dp[v][0] <= dp[v][1]) {
41             flag = true;
42             dp[u][1] += dp[v][0];
43         } else {
44             dp[u][1] += dp[v][1];
45             Min = min(dp[v][0] - dp[v][1], Min);
46         }
47     }
48     if(!flag) //要是没取到dp[v][0]
49         dp[u][1] += Min;
50 }
51 
52 int main()
53 {
54     int n, u, v;
55     while(~scanf("%d", &n)) {
56         memset(head, -1, sizeof(head));
57         cnt = 0;
58         for(int i = 1; i < n; ++i) {
59             scanf("%d %d", &u, &v);
60             add(u, v);
61             add(v, u);
62         }
63         dfs(1, -1);
64         printf("%d
", min(dp[1][0], dp[1][1]));
65     }
66     return 0;
67 }
原文地址:https://www.cnblogs.com/Recoder/p/5838283.html