Luogu P3523 [POI2011]DYN-Dynamite
作者:互联网
如此多的最大最小,显然二分答案mid,则对于每一个关键点到所选的最近的点的距离<=mid
貌似是树形DP
令f[i]表示以i为根的子树中i到最远关键点(无人认领)的距离,
g[i]表示 i到最近选出点的距离
f[u]=max(f[v]+1),g[u]=min(g[v]+1);
如果f[u]=mid,那么无论如何,u都要被选,f[u]=-oo,g[u]=0,sum++;
如果u是关键点,那么f[u]=max(0,f[u]);
如果f[u]+g[u]<=mid,即可以在子树内部自己消化,故f[u]=-oo
最后注意f[1]>=0的时候要把1设为关键点。
注意特判超脱于五行之上的0(^.^)
#include<bits/stdc++.h> const int INF=1e9; using namespace std; const int N=6e5+5; int cnt,to[N],nxt[N],he[N],f[N],g[N],sum,n,m; bool a[N]; inline void add(int u,int v) { to[++cnt]=v,nxt[cnt]=he[u],he[u]=cnt; } void dfs(int fa,int u,int k) { g[u]=INF,f[u]=-INF; for(int e=he[u];e;e=nxt[e]) { int v=to[e]; if(v!=fa){ dfs(u,v,k); f[u]=max(f[v]+1,f[u]); g[u]=min(g[v]+1,g[u]); } } if(f[u]==k) f[u]=-INF,g[u]=0,sum++; if(a[u]) f[u]=max(f[u],0); if(f[u]+g[u]<=k) f[u]=-INF; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]) sum++; } if(sum==m) { puts("0"); return 0; } for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v),add(v,u); } int l=1,r=n,ans; while(l<=r) { int mid=l+r>>1; sum=0; dfs(0,1,mid); if(f[1]>=0) sum++; if(sum<=m) { r=mid-1; ans=mid; } else l=mid+1; } printf("%d\n",ans); return 0; }
标签:cnt,int,Luogu,sum,POI2011,++,DYN,max,he 来源: https://www.cnblogs.com/wsfwsf/p/13604281.html