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\n",ans); 44 return 0; 45 }