题面:
Cornered at last, Bessie has gone to ground in a remote farm. The farm consists of N barns (2≤N≤1e5) and N−1 bidirectional tunnels between barns, so that there is a unique path between every pair of barns. Every barn which has only one tunnel is an exit. When morning comes, Bessie will surface at some barn and attempt to reach an exit.
But the moment Bessie surfaces, the law will be able to pinpoint her location. Some farmers will then start at various exit barns, and attempt to catch Bessie. The farmers move at the same speed as Bessie (so in each time step, each farmer can move from one barn to an adjacent barn). The farmers know where Bessie is at all times, and Bessie knows where the farmers are at all times. The farmers catch Bessie if at any instant a farmer is in the same barn as Bessie, or crossing the same tunnel as Bessie. Conversely, Bessie escapes if she reaches an exit barn before any farms catch her.
Bessie is unsure about her chances of success, which depends on the number of farmers that the law is able to deploy. Given that Bessie surfaces at barn K, help Bessie determine the minimum number of farmers who would be needed to catch Bessie, assuming that the farmers distribute themselves optimally among the exit barns.
INPUT
The first line of the input contains N and K. Each of the following N−1 lines specify two integers, each in the range 1…N, describing a tunnel between two barns.
OUTPUT
Please output the minimum number of farmers needed to ensure catching Bessie.
SAMPLE INPUT:
7 1
1 2
1 3
3 4
3 5
4 6
5 7
SAMPLE OUTPUT:
3
题意:
有一棵树,一只羊在其中的一个点上。树的叶子节点是出口,牧羊人从叶子节点出发去抓羊,当牧羊人和样通过同一条边或者在同一个点上就认为羊被抓住。询问最少需要几个牧羊人才能保证羊在跑出出口前被抓到。
思路:
双向bfs,先把所有的叶子节点放入队列,再把羊的起点放入队列,然后搜索即可。具体见代码注释。
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int head[N],cnt=0;
struct node{
int v,nxt;
}edge[N<<1];
void addedge(int u,int v){
edge[++cnt].v=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
int du[N];//记录节点的度数
struct node2{
int x,fa;//当前节点,父亲节点
bool type;//true:羊出发的 false:牧羊人出发的
node2(){}
node2(int x,int fa,bool type){
this->x=x;
this->fa=fa;
this->type=type;
}
};
queue<node2>q;
int ans=0;
int vis1[N],vis2[N];//分别记录一个节点有没有被羊访问,有没有被牧羊人访问
void bfs(){
while(!q.empty()){
node2 now=q.front();
q.pop();
for(int i=head[now.x];~i;i=edge[i].nxt){
int v=edge[i].v;
if(v==now.fa)continue;
if(now.type){//如果是羊出发的
if(du[v]!=1){//被牧羊人访问过,结束
if(vis2[v]){
continue;
}
else{//没被牧羊人访问则继续前进
vis1[v]=1;
q.push(node2(v,now.x,now.type));
}
}
else{//到达出口,结束
continue;
}
}
else{//牧羊人的情况
if(vis1[v]){//如果被羊访问过,需要统计答案,并结束
ans++;
continue;
}
else if(vis2[v])continue;//被其他牧羊人访问过,也要结束
else{//其余情况继续前进
vis2[v]=1;
q.push(node2(v,now.x,now.type));
}
}
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
for(int i=1,u,v;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
du[u]++,du[v]++;
}
if(du[m]==1){//特判羊在叶子上的情况
printf("1\n");
return 0;
}
//先放牧羊人,后放羊
for(int i=1;i<=n;i++){
if(du[i]==1){
q.push(node2(i,-1,false));
}
}
q.push(node2(m,0,true));
vis1[m]=1;
bfs();
printf("%d\n",ans);
return 0;
}