@ysner
2018-10-09T14:56:07.000000Z
字数 1318
阅读 2460
贪心 树形DP DP
在大小为的树上选择尽量少的点,使得所有未选择的点距离选择了的点小于等于。
令为正整数。
设为距离最近的,选择了的点,还能向上覆盖的距离为。这类标记称为。
设为距离最近的,选择了的点,的覆盖范围为。这类标记陈伟
(、主要是为了避免的两重含义)
给所有叶结点打这个标记。
向上汇集标记时,如果,说明点可以被下面的某个选择了的点覆盖到,取标记。
否则取标记。
同时如果,这个点必须被选择(否则就有点覆盖不到)。
特别注意根结点。
如果到根时标记为负数,根需要单独放个标记(因为没有点在更上面覆盖它了)。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define ll long long#define re register#define il inline#define fp(i,a,b) for(re int i=a;i<=b;i++)#define fq(i,a,b) for(re int i=a;i>=b;i--)using namespace std;const int N=1e5+100;int n,k,t,f[N],g[N],h[N],cnt;struct Edge{int to,nxt;}e[N<<1];il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;}il int gi(){re int x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t;}il void dfs(re int u,re int fa){re int mor=0,les=-1,son=0;for(re int i=h[u];i+1;i=e[i].nxt){re int v=e[i].to;if(v==fa) continue;++son;dfs(v,u);g[u]+=g[v];--f[v];if(!f[v]) --f[v];if(f[v]>0) mor=max(mor,f[v]);else les=min(les,f[v]);}if(abs(mor)>=abs(les)) f[u]=mor;else if(les<=-k-1||u==1) f[u]=k+1,++g[u];else f[u]=les;}int main(){memset(h,-1,sizeof(h));n=gi();k=gi();gi();fp(i,1,n-1){re int u=gi(),v=gi();add(u,v);add(v,u);}dfs(1,0);printf("%d\n",g[1]);return 0;}
