题目
https://codeforces.com/gym/102411/problem/E
题目大意
给定一棵树及若干询问节点,问树上是否存在一点到若干询问节点的距离相等。(所有边权为1)
思路
多源BFS,注意只有要跳过去的点未被访问过,或者是同一时间访问的,才是合法的跳动。
用dep[ ]数组记录节点深度也就是首次访问该节点的时间。
AC代码
#include<bits/stdc++.h>
#define pb push_back
#define lowbit(x) x&(-x)
#define mst(a,b) memset(a,b,sizeof a)
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const int Mod = 1e9+7;
const int N = 2e5+10;
ll Read(){
ll val = 0, opt = 1; char ch;
while (!isdigit(ch = getchar())) if (ch == '-') opt = -1;
while (isdigit( ch )) (val *= 10) += ch - '0', ch = getchar();
return val * opt;
}
struct node{
int to,nxt;
} edge[2 * N];
int head[N],cnt,vis[N],dep[N],sz[N];
int m,n;
queue<int> q;
void add(int u, int v){
edge[cnt].to = v;
edge[cnt].nxt = head[u];
head[u] = cnt++;
}
void bfs(){
while(!q.empty()){
int x = q.front();q.pop();
for(int i = head[x]; i>=0 ; i = edge[i].nxt){
int to = edge[i].to;
if(dep[to]==0 || dep[to]==dep[x]+1){ //△
dep[to] = dep[x] + 1;
sz[to] += sz[x];
if(sz[to] == m){
printf("YES\n%d\n", to);
exit(0);
}
}
if(!vis[to]){ //每个点最多进入队列一次
q.push(to);
vis[to] = 1;
}
}
}
}
signed main(){
n = Read(); m = Read();
memset(head,-1,sizeof(head));
int a,b;
for(int i=0;i<n-1;i++){
a=Read();b=Read();
add(a,b);
add(b,a);
}
for(int i=0;i<m;i++){
a = Read();
q.push(a);
dep[a] = 1;
vis[a] = 1;
sz[a] = 1;
}
if(m == 1){
printf("YES\n%d\n", a);
return 0;
}
bfs();
printf("NO\n");
return 0;
}