luogu2279 消防局的设立 (贪心)

按点的深度从大到小排序,每次取出深度最大的那个点,如果它还没被覆盖,就在它爷爷上放一个消防局,这样一定是最优的

为了判定是否被覆盖,可以记录从某点的子树中到这个点的最近消防局的距离dis[](如果没有就是inf呗)

这样的话,对于x,如果dis[x]<=2或者dis[fa[x]]<=1或者dis[fa[fa[x]]]<=0,他就已经被覆盖了,直接跳过

用这种方法,可以做覆盖范围更大的

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1010,inf=1e9;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 int N,md[maxn],fa[maxn],dep[maxn],id[maxn];
16 
17 inline bool cmp(int x,int y){return dep[x]>dep[y];}
18 
19 int main(){
20     //freopen("","r",stdin);
21     int i,j,k;
22     N=rd();
23     dep[1]=id[1]=1;md[1]=inf;
24     for(i=2;i<=N;i++){
25         fa[i]=rd();id[i]=i;
26         md[i]=inf;
27         dep[i]=dep[fa[i]]+1;
28     }
29     sort(id+1,id+N+1,cmp);
30     int ans=0;
31     for(i=1;i<=N;i++){
32         int x=id[i];
33         if(md[x]<=2||(fa[x]&&(md[fa[x]]<=1||(fa[fa[x]]&&md[fa[fa[x]]]<=0)))) continue;
34         int f=fa[x]?(fa[fa[x]]?fa[fa[x]]:fa[x]):x;
35         md[f]=0;
36         ans++;
37         if(fa[f]){
38             md[fa[f]]=min(md[fa[f]],1);
39             if(fa[fa[f]])
40                 md[fa[fa[f]]]=min(md[fa[fa[f]]],2);
41         }
42     }
43     printf("%d
",ans);
44     return 0;
45 }
原文地址:https://www.cnblogs.com/Ressed/p/9811142.html