链接:http://codeforces.com/problemset/problem/686/D
寻找以i为根的子树的重心 当我们要求ans[i]的时候可以发现ans[i]一定会在i节点儿子中数量最多的子树当中,所以层层往上推 直到ans[i]=i || d[i]-d[ans[i]]<d[i]/2;
#include <bits/stdc++.h>
using namespace std;
const int N=3e5+5;
vector<int>G[N];
int n,m,f[N],ans[N],d[N]; //d[i] 是记录以i为根节点的子数节点大小 ans[i] 为i的重心结果 f[i] 为i的父亲
void dfs(int u)
{
int tol=1,ma=0,an=u;
ans[u]=u;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
dfs(v);
tol+=d[v];
if(ma<d[v])
{
ma=d[v];
an=v;
}
}
ans[u]=ans[an];
d[u]=tol;
while(ans[u]!=u&&d[u]-d[ans[u]]>d[u]/2)
ans[u]=f[ans[u]];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=2;i<=n;i++)
{
int u;
scanf("%d",&u);
G[u].push_back(i);
f[i]=u;
}
dfs(1);
while(m--)
{
int rt;
scanf("%d",&rt);
printf("%d\n",ans[rt]);
}
return 0;
}