Problem
B
e
s
s
i
e
Bessie
Bessie 站在一个点,每个叶节点可以放一个士兵,士兵和
B
e
s
s
i
e
Bessie
Bessie 都可以随意走动。
如果士兵和
B
e
s
s
i
e
Bessie
Bessie 在同一点,那么
B
e
s
s
i
e
Bessie
Bessie 就被抓住。
而
B
e
s
s
i
e
Bessie
Bessie 如果到达叶节点且一路上没有被士兵抓住,则算
B
e
s
s
i
e
Bessie
Bessie 出逃成功。
每一时刻,士兵能知道
B
e
s
s
i
e
Bessie
Bessie 在哪,且
B
e
s
s
i
e
Bessie
Bessie 也知道士兵在哪。
问能抓住
B
e
s
s
i
e
Bessie
Bessie 所需最少士兵数为多少。
Solution
显然对应每个点来说,如果有一个士兵(从下往上)能比
B
e
s
s
i
e
Bessie
Bessie (从上往下)先到,则说明这棵子数只需要这一个士兵即可。
因此以
B
e
s
s
i
e
Bessie
Bessie 初始所在的点为根。
如果某一点到根距离大于最近的到叶节点距离,那么说明这棵子树只需要一个人从最近的叶节点出发即可。否则继续递归下去就好啦。
Code
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
#define inf 0x3f3f3f3f
int n,m,root=0,ans=0,num=0,mn[N],h[N],d[N];
struct node{int to,next;}mp[N<<1];
inline void insert(int x,int y){
mp[++num].to=y;mp[num].next=h[x];h[x]=num;
mp[++num].to=x;mp[num].next=h[y];h[y]=num;
}
void dfs(int x){
mn[x]=inf;int tot=0;
for(int i=h[x];i;i=mp[i].next){
int y=mp[i].to;if(d[y]) continue;
d[y]=d[x]+1;tot++;dfs(y);
mn[x]=min(mn[x],mn[y]+1);
}
if(!tot) mn[x]=0;
}
void calc(int x){
if(mn[x]<d[x]){ans++;return;}
for(int i=h[x];i;i=mp[i].next){
int y=mp[i].to;if(d[y]!=d[x]+1) continue;
calc(y);
}
}
int main(){
scanf("%d%d",&n,&root);
for(int i=1;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
insert(x,y);
}d[root]=1;dfs(root);calc(root);
printf("%d\n",ans);
return 0;
}