[POI2011]DYN-Dynamite
Posted nldqy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POI2011]DYN-Dynamite相关的知识,希望对你有一定的参考价值。
题目链接:Click here
Solution:
直接做似乎不太可行,我们考虑二分
我们设\(f[x]\)表示以\(x\)为根的子树中选择了的节点到\(x\)的距离的最小值,初值为\(inf\)
\(g[x]\)则表示以\(x\)为根的子树中还未覆盖的关键点到\(x\)的距离的最大值,初值为\(-inf\)
考虑如何转移,当\(f[x]>mid\)且\(x\)是关键点时,则说明\(x\)自己并没有被覆盖,\(g[x]=max(0,g[x])\)
当\(g[x]+f[x]<=mid\)时,则说明\(x\)子树内的所有点都被覆盖了,那么我们把\(g[x]\)重置
当\(g[x]==mid\)时,则说明\(x\)这个点一定要选,那么\(++tot\,,f[x]=0\, ,g[x]=-inf\)
事实上上述的\(dp\)过程是不能随意更换顺序的,并且由于我们贪心的先处理儿子,所以还需要特判根节点
Code:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
using namespace std;
const int N=3e5+11;
const int inf=192608170;
int n,m,cnt,head[N];
int tot,f[N],g[N],is[N];
struct Edgeint nxt,to;edge[N<<1];
void ins(int x,int y)
edge[++cnt].nxt=head[x];
edge[cnt].to=y;head[x]=cnt;
void dfs(int x,int fa,int mid)
f[x]=inf,g[x]=-inf;
for(int i=head[x];i;i=edge[i].nxt)
int y=edge[i].to;
if(y==fa) continue;
dfs(y,x,mid);
f[x]=min(f[x],f[y]+1);
g[x]=max(g[x],g[y]+1);
if(is[x]&&f[x]>mid) g[x]=max(0,g[x]);
if(f[x]+g[x]<=mid) g[x]=-inf;
if(g[x]==mid) f[x]=0,g[x]=-inf,++tot;
bool check(int mid)
tot=0;dfs(1,0,mid);
if(g[1]>=0) ++tot;
return tot<=m;
int read()
int x=0,f=1;char ch=getchar();
while(!isdigit(ch))if(ch=='-')f=-f;ch=getchar();
while(isdigit(ch))x=x*10+ch-48;ch=getchar();
return x*f;
signed main()
n=read(),m=read();
for(int i=1;i<=n;i++) is[i]=read();
for(int i=1;i<n;i++)
int x=read(),y=read();
ins(x,y),ins(y,x);
int l=0,r=n,re=-1;
while(l<=r)
int mid=l+r>>1;
if(check(mid)) re=mid,r=mid-1;
else l=mid+1;
printf("%d\n",re);
return 0;
以上是关于[POI2011]DYN-Dynamite的主要内容,如果未能解决你的问题,请参考以下文章