Luogu 2279 [HNOI2003]消防局的设立

Description

给定一棵树形图, 建若干个消防站, 消防站能够覆盖到距离不超过2的点, 求最少需要建几个消防站才能覆盖所有点

Solution

从深度最深的点开始, 在它的爷爷节点上建, 每建一次都要把能覆盖的点都记录下来。

执行的次数就是答案。

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rd read()
 5 using namespace std;
 6 
 7 const int N = 1e3 + 5;
 8 
 9 int n, f[N], id[N], vis[N], dep[N];
10 int ans, head[N], tot;
11 
12 struct edge {
13     int nxt, to;
14 }e[N];
15 
16 int read() {
17     int X = 0, p = 1; char c = getchar();
18     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
19     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
20     return X * p;
21 }
22 
23 void add(int u, int v) {
24     e[++tot].to = v;
25     e[tot].nxt = head[u];
26     head[u] = tot;
27 }
28 
29 int cmp(int a, int b) {
30     return dep[a] > dep[b];
31 }
32 
33 void dfs(int x) {
34     if(!x) return;
35     vis[x] = 1;
36     for(int i = head[x]; i; i = e[i].nxt) {
37         int nt = e[i].to;
38         vis[nt] = 1;
39     }
40 }
41 
42 void col(int x) {
43     vis[x] = 1; vis[f[x]] = 1;
44     dfs(f[x]); dfs(f[f[x]]);
45     x = f[f[x]];
46     vis[x] = 1; vis[f[x]] = 1;
47     dfs(f[x]);
48     vis[f[f[x]]] = 1;
49     for(int i = head[x]; i; i = e[i].nxt) dfs(e[i].to);
50 }
51 
52 int main()
53 {
54     n = rd;
55     dep[1] = 1;
56     for(int i = 2; i <= n; ++i) {
57         f[i] = rd;
58         dep[i] = dep[f[i]] + 1;
59         add(f[i], i);
60     }
61     for(int i = 1; i <= n; ++i) id[i] = i;
62     sort(id + 1, id + n + 1, cmp);
63     for(int i = 1; i <= n; ++i) {
64         if(vis[id[i]]) continue;
65         ans++;
66         col(id[i]);
67     }
68     printf("%d
", ans);
69 }
View Code
原文地址:https://www.cnblogs.com/cychester/p/9574857.html