LUOGU P2279 [HNOI2003]消防局的设立
解题思路
和以前做的一道题比较像,贪心+dfs,首先用一个优先队列,将所有的叶节点存到优先队列里,每次找到一个深度最大的,向上扩展2*2+1个节点,这些点都打上标记,然后把向上第6个点的当做叶节点继续放入优先队列,直到所有点被遍历。时间复杂度O(nlogn)。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN = 1005; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } struct Data{ int dep,id; friend bool operator<(const Data A,const Data B) { return A.dep<B.dep; } }; int n,k,head[MAXN],cnt,du[MAXN],num,deep[MAXN]; int to[MAXN<<1],nxt[MAXN<<1],ans; bool vis[MAXN]; priority_queue<Data> Q; inline void add(int bg,int ed){ to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt; } void dfs(int x,int fa,int d){ deep[x]=d; if(du[x]==1 && x!=1) {Q.push(Data{d,x});return;} for(register int i=head[x];i;i=nxt[i]){ int u=to[i];if(u==fa) continue; dfs(u,x,d+1); } } void dfs2(int x,int fa,int len){ if(len==k*2+1) {if(!vis[x]) Q.push((Data){deep[x],x});return;} vis[x]=1; for(register int i=head[x];i;i=nxt[i]){ int u=to[i];if(u==fa) continue; dfs2(u,x,len+1); } } int main(){ n=rd();int x;k=2; for(int i=1;i<n;i++){ x=rd(); add(x,i+1),add(i+1,x); du[x]++,du[i+1]++; } dfs(1,0,0); while(Q.size()){ Data now=Q.top();Q.pop(); if(vis[now.id]) continue; // cout<<now.id<<endl; dfs2(now.id,0,0);ans++; } cout<<ans<<endl; return 0; }