为了方便,以目标为根,向深度浅的位置走为“向上走”,否则为“向下走”。
考虑到老鼠一旦开始向下走,它就一定会一直向下,直到走到叶子或者唯一向下的路被堵住了,此时只需要封住所有岔路并擦干即可。
设 \(f_i\) 表示将老鼠从 \(i\) 赶回 \(i\) 的最优解。
首先,\(i\) 的所有子树必须被封上/擦干一次,否则老鼠蹿上来后又回进入其他子树。
由于博弈,所以老鼠会选择子树中 \(f\) 大的走,由于只能封一个,所以会选次大的走(不存在的话路直接就给堵死了,为 \(0\))
\(f_u=\operatorname{2ndmax}\limits_{v\in son_u} f_v+\deg u-1\)
考虑设 \(h(u)\) 表示 \(u\rightarrow rt\) 的所有岔边,\(g_u\) 表示从进入 \(u\) 到回到根的最优解。
由于如果存在“向上走”,则有一条边会不用堵。
\(g_u=h(fa_u)+f_u-[fa_u\not=m]\)
接下来的问题是不清楚老鼠会向上跳到哪里,所以考虑二分答案。
注意到我们没有办法阻止老鼠上跳,所以只能和老鼠拼手速,堵住所有会使答案 \(>mid\) 的路。
如果始终能堵住,那么答案显然不超过 \(mid\)。注意不能让封堵的总次数 \(>mid\)。
#include <cstdio>
#include <algorithm>
#include <cctype>
using namespace std;
char buf[1<<14],*p1=buf,*p2=buf;
#define GetC() ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++)
struct Ios{}io;
template <typename _tp>
Ios &operator >>(Ios &in,_tp &x){
x=0;int w=0;char c=GetC();
for(;!isdigit(c);w|=c=='-',c=GetC());
for(;isdigit(c);x=x*10+(c^'0'),c=GetC());
if(w) x=-x;
return in;
}
const int N=1e6+5;
int n,t,m;
struct EDGE{ int nxt,to; }e[N<<1];
int head[N],tot;
void add(int from,int to){
e[++tot].nxt=head[from];
e[tot].to=to;
head[from]=tot;
}
int dp[N],deg[N],h[N],f[N],g[N];
int st[N],top;
void dfs(int u,int fa){
f[u]=fa;
dp[u]=0;
int mx1=0,mx2=0;
if(fa) h[u]=h[fa]+deg[u]-1-(fa!=0);
else h[u]=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue ;
dfs(v,u);
if(dp[v]>=mx1) mx2=mx1,mx1=dp[v];
else mx2=max(mx2,dp[v]);
}
dp[u]=mx2+deg[u]-1;
if(fa==0) dp[u]=0;
}
bool check(int x){
int sum=0,tmp=0;
for(int i=1;i<top;++i){
int u=st[i];
tmp=0;
for(int _=head[u];_;_=e[_].nxt){
int v=e[_].to;
if(v==st[i+1]||v==st[i-1]) continue ;
if(dp[v]>x) ++tmp;
}
sum+=tmp;x-=tmp;
if(x<0||sum>i) return false;
}
return true;
}
int main(){
io>>n>>t>>m;
if(t==m){
puts("0");
return 0;
}
for(int i=1;i<n;++i){
int u,v;io>>u>>v;
add(u,v);add(v,u);
++deg[u];++deg[v];
}
dfs(t,0);
for(int i=1;i<=n;++i){
if(i!=t){
dp[i]+=h[f[i]]+(f[i]==m);
}
}
for(int i=m;i;i=f[i]) st[++top]=i;
int l=0,r=2*n;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)) r=mid-1;
else l=mid+1;
}
printf("%d\n",l);
return 0;
}
标签:P4654,return,int,mx2,mid,CEOI2017,Mousetrap,dp,deg
From: https://www.cnblogs.com/pref-ctrl27/p/17037148.html