题意:求出以每个点为子树的重心。
思路:可以利用重心的性质,某一个点的重心在最大的点那个子树上,并且在在这个节点到最大子树的重心之间,重心满足num[x] * 2 > num[u],x为重心,u为要求重心的节点,num[]代表这个节点的子树的节点个数。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int maxn = 300000 + 10;
typedef long long ll;
vector<int>g[maxn];
int fa[maxn];
int num[maxn];
int ans[maxn];
void dfs(int u)
{
num[u] = 1;
int pos,t = 0;
for(int i = 0; i < g[u].size(); i ++)
{
int v = g[u][i];
dfs(v);
if(num[v] > t)t = num[v],pos = v;
num[u] += num[v];
}
if(num[u] == 1 || num[u] == 2)
{
ans[u] = u;
return;
}
int x= ans[pos];
while(num[x] * 2 < num[u])
x = fa[x];
ans[u] = x;
}
int main()
{
int n,m;
while( ~ scanf("%d%d",&n,&m))
{
memset(ans,0,sizeof(ans));
for(int i = 0; i <= n; i ++)
g[i].clear();
fa[1] = 1;
for(int i = 2; i <= n; i ++)
{
int x;
scanf("%d",&x);
fa[i] = x;
g[x].push_back(i);
}
dfs(1);
for(int i = 1; i <= m; i ++)
{
int x;scanf("%d",&x);
printf("%d\n",ans[x]);
}
}
return 0;
}