洛谷 P2279 [HNOI2003]消防局的设立 题解

每日一题 day34 打卡

Analysis

这道题的正解本来是树形dp,但要设5个状态,太麻烦了。于是我就用贪心试图做出此题,没想到还真做出来了。

考虑当前深度最大的叶子结点,你肯定要有一个消防局去覆盖它,

那么既然他是叶子结点,所以与他距离小于等于2的节点有这么

  1. 他的父亲 2. 他的兄弟 3. 他的爷爷

容易看出,在前两项能够覆盖到的节点,在爷爷那里设立一定也能覆盖到。

所以每次贪心取出深度最大的节点,在他的爷爷哪里放一个消防站

用STL的priority_queue,时间复杂度O(nlogn)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #define int long long
 8 #define R register
 9 #define maxn 1000+10
10 #define rep(i,s,e) for(register int i=s;i<=e;++i)
11 using namespace std;
12 inline int read()
13 {
14     int x=0;
15     bool f=1;
16     char c=getchar();
17     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
18     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
19     if(f) return x;
20     return 0-x;
21 }
22 inline void write(int x)
23 {
24     if(x<0){putchar('-');x=-x;}
25     if(x>9)write(x/10);
26     putchar(x%10+'0');
27 }
28 int n,cnt,ans;
29 int head[maxn*maxn],dep[maxn],fa[maxn],book[maxn];
30 struct node
31 {
32     int v,nex;
33 }edge[2*maxn*maxn];
34 struct cmp
35 {
36     bool operator () (int &a,int &b)
37     {
38         return dep[a]<dep[b];
39     } 
40 };
41 priority_queue<int,vector<int>,cmp> q;
42 inline void add(int x,int y)
43 {
44     edge[++cnt].v=y;
45     edge[cnt].nex=head[x];
46     head[x]=cnt;
47 }
48 void calc_deep(int from,int father,int deep)
49 {
50     dep[from]=deep;
51     fa[from]=father;
52     for(int i=head[from];i;i=edge[i].nex)
53     {
54         int to=edge[i].v;
55         if(to==father) continue;
56         calc_deep(to,from,deep+1);
57     }
58 }
59 void update(int from,int wide)
60 {
61     if(wide>2) return;
62     book[from]=1;
63     for(int i=head[from];i;i=edge[i].nex)
64     {
65         int to=edge[i].v;
66         update(to,wide+1);
67     }
68 }
69 signed main()
70 {
71     n=read();
72     rep(i,1,n-1) 
73     {
74         int x=read();
75         add(i+1,x);add(x,i+1);
76     }
77     calc_deep(1,0,1);
78     rep(i,1,n) q.push(i);
79     while(!q.empty())
80     {
81         while(!q.empty()&&book[q.top()]==1) q.pop();
82         if(q.empty()==1) break;
83         if(fa[fa[q.top()]]==0) update(1,0);
84         else if(fa[fa[q.top()]]>0) update(fa[fa[q.top()]],0);
85         ans++;
86     }
87     write(ans);
88     return 0;
89 }

请各位大佬斧正(反正我不认识斧正是什么意思)

原文地址:https://www.cnblogs.com/handsome-zyc/p/11837366.html