消防局的设立
贪心:每次取出深度最大的节点,若没有被覆盖到,要想覆盖它,
最优的做法显然是将它的爷爷设为消防局
(因为该节点深度为最大,选兄弟、父亲所覆盖的节点,选了爷爷后都能够覆盖)
用优先队列维护深度即可
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define INF 100000 #define N 1010 int n,Head[N],num,ans,fa[N]; int ok[N],deep[N],vis[N]; struct cmp{ bool operator ()(int a,int b){ return deep[a]<deep[b]; } }; struct NODE{ int to,next; } e[N<<1]; priority_queue< int, vector<int>, cmp > q; inline int read(){ int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } return x; } inline void add(int x,int y){ e[++num].to=y; e[num].next=Head[x]; Head[x]=num; } void dfs(int t,int f){ fa[t]=f; deep[t]=deep[f]+1; for(int i=Head[t];i;i=e[i].next) if(e[i].to!=f) dfs(e[i].to,t); } void dfs2(int t,int dep){ if(dep==2) return; for(int i=Head[t];i;i=e[i].next){ int v=e[i].to; vis[v]=1; dfs2(v,dep+1); } } int main() { n=read(); int x; for(int i=2;i<=n;i++){ x=read(); add(i,x); add(x,i); } dfs(1,-1); for(int i=1;i<=n;i++) q.push(i); int u,gf; while(!q.empty()){ u=q.top(); q.pop(); if(vis[u]) continue; ans++; if(fa[u]!=-1) if(fa[fa[u]]!=-1) gf=fa[fa[u]]; else gf=fa[u]; else gf=u; vis[gf]=1; dfs2(gf,0); } printf("%d ",ans); return 0; }