题目:
ICPC 2019-2020 North-Western Russia Regional Contest
题意:
给定一颗树,再给出 m 个关键点,让你找出一个点使得这个点到 m 个关键点的距离相等
分析:
(1)直观的做法就是换根dp,预处理出每个节点为根时,子树中的关键点到它距离最大值和最小值,次最大值和次最小值,换根dp的时候直接看所有关键点到根的最大值和最小值是否相等
(2)问题可以转换为找到一个点,使得所有关键点到它距离的最大值最小,这个点一定是关键点的直径上的中点,这个点一定是唯一的,先两边 dfs 找到直径,再找到中点,最后判断一下这个中点是否满足题意即可
代码:
#include <bits/stdc++.h>
#define f first
#define s second
#define pii pair<int,int>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long LL;
const int maxn = 2e5+25;
int head[maxn],n,m,u,v,cnt,d[maxn],tag[maxn],p[maxn];
struct edge{
int to,nxt;
}e[maxn<<1];
inline void add(int u,int v){
e[++cnt] = (edge){v,head[u]};
head[u] = cnt;
}
int x,len;
void dfs(int u,int fa,int step){
if(tag[u]&&step>=len){
x = u; len = step;
}
for(int i = head[u];i > 0;i = e[i].nxt){
int v = e[i].to; if(v == fa) continue;
dfs(v,u,step+1);
}
}
bool flag;
int q[maxn],k;
void dfs2(int u,int fa){
q[k++] = u;
if(u =&#