[BZOJ1217][HNOI2003]消防局的设立(贪心)
这题也有树规的打法,但好复杂啊
贪心是这样的,对于深度最深的一个叶子节点,要覆盖它的话,肯定是覆盖它的爷爷是最优的
这样它的父亲跟兄弟都会被覆盖
所以每次找深度最深的,覆盖它的爷爷就行了
Code
#include <cstdio> #include <algorithm> #include <queue> #include <vector> #define N 1010 using namespace std; int n,head[N],tot,dep[N],fa[N],Ans; struct info{int to,nex;}e[N*2]; struct cmp{bool operator() (int a,int b){return dep[a]<dep[b];}}; priority_queue<int,vector<int>,cmp> q; bool vis[N]; inline void Link(int u,int v){ e[++tot].to=v;e[tot].nex=head[u];head[u]=tot; } inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void dfs(int u,int fa){ for(int i=head[u];i;i=e[i].nex){ int v=e[i].to; if(v==fa) continue; dep[v]=dep[u]+1; ::fa[v]=u; dfs(v,u); } } void dddfs(int u,int dp){ if(dp>2) return; vis[u]=1; for(int i=head[u];i;i=e[i].nex) dddfs(e[i].to,dp+1); } int main(){ n=read(); for(int i=2;i<=n;++i){ int v=read(); Link(i,v),Link(v,i); } dfs(1,0); for(int i=1;i<=n;++i) q.push(i); while(!q.empty()){ while(!q.empty()&&vis[q.top()]) q.pop(); if(q.empty()) break; dddfs(fa[fa[q.top()]]?fa[fa[q.top()]]:1,0); ++Ans; } printf("%d\n",Ans); return 0; }