将军令题解
将军令题解
首先,每个叶子节点都要被至少一个小队控制,
则贪心地放置小队,
放置之后没被覆盖的点跟属于控制范围的点无关,
又属于新的“叶子”,继续递归。
如何贪心地放置?
对于每一个点,我们求出离它最远的没被覆盖的点,
若距离超过k-它离最近的小队的距离,
则必定放置小队,
并把离它距离小于等于k的父亲标记,值为离它距离。
#include<bits/stdc++.h>
using namespace std;
const int N=200006;
int n,t,t1,t2,k,cnt=0,ans=0,f[N],dis[N],head[N];
//f[x]:x的父亲,dis[x]:x到最近的小队的距离
struct edge{int nxt,to;}e[N<<1];
inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;}
inline int read(){
int T=0,F=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
return F*T;
}
int dfs(int x){
int maxa=1;
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=f[x])
f[e[i].to]=x,maxa=max(maxa,dfs(e[i].to)+1);
if(maxa>k){
if(dis[x]<maxa){
++ans,t=x;
for(int i=k+1;i>=1;--i) dis[t]=max(dis[t],i),t=f[t];
}
}
if(dis[x]&&dis[x]>=maxa) maxa=0;
if(x==1&&dis[x]<maxa) ++ans;
return maxa;
}
int main(){
n=read(),k=read(),t=read();
for(int i=2;i<=n;++i) t1=read(),t2=read(),add(t1,t2),add(t2,t1);
dfs(1),printf("%d",ans);
return 0;
}