Problem
给定一棵树和树上一些点,求任意一个树上到所有给定点距离相等的点。
Solution
- 直接对所有选中的点往外bfs,但是需要一些超越常数的优化,要不然又TLE又MLE。记录所有选出的点到每个点的最短距离,记录选中的点在最短距离下到达其他点的次数,只在第一次访问的时候(最短距离)push(这样保证了每个点只进队一次),相等的时候更新最短距离下到达的该点的所选中点的数量。
- 注意检查极限情况是否能算对。
Code(写的很乱)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=2e5+5;
int n,m,cnt,last[maxn],d[maxn],tim[maxn],ac;
bool ans,inq[maxn];
struct edge
{
int v,next;
} e[maxn*2];
struct node
{
int u,f;
};
inline void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].next=last[u];
last[u]=cnt;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,u,v; i<=n-1; i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
queue<node>q;
memset(d,-1,sizeof(d));
for(int i=1,u; i<=m; i++)
{
scanf("%d",&u);
q.push({u,0});
d[u]=0;
tim[u]++;
ac=u;
}
if(m==1)
ans=1;
while(!q.empty())
{
node nw=q.front();
q.pop();
int u=nw.u,f=nw.f;
for(int i=last[u]; i; i=e[i].next)
{
int v=e[i].v;
if(d[v]==-1)
{
d[v]=d[u]+1;
q.push({v,u});
}
if(v==f) continue;
if(d[v]==d[u]+1)
tim[v]+=tim[u];
if(tim[v]==m)
{
ans=1;
ac=v;
break;
}
}
if(ans) break;
}
if(ans)
cout<<"YES"<<endl<<ac;
else
cout<<"NO";
return 0;
}