1. 程式人生 > 實用技巧 >html基本結構

html基本結構

題面跳轉

這道題我用的是vector存的圖,d[]表示該節點的大小(包括自己),fa[i]就表示i這個節點的父親節點

在dfs的時候進行vector遍歷就行

性質:

一個樹的重心一定在他所有兒子的子樹的重心的連線上。

#include<bits/stdc++.h>
using namespace std ;
const int maxn=300100;
int n,q;
int d[maxn];
vector<int >tree[maxn];
int ans[maxn];
int fa[maxn];
void dfs(int u,int father)
{
	d[u]=1;
	int minNode=0;
	int size=tree[u].size();
	ans[u]=u;
	for(int i=0;i<size;i++)
	{
		int v=tree[u][i];
		if(v!=father)
		{
			dfs(v,u);
			d[u]+=d[v];
			if(d[v]>d[minNode])
			minNode=v;
		}
	}
    if(d[minNode]*2>d[u])//minnode表示這個節點的子樹中,子節點大小最大的編號 
    {
    	int k=ans[minNode];//mindnode的重心一定比這個節點的重心深 ,所以k從這個位置開始一定不會漏掉正確的答案 
    	while(d[u]>d[k]*2)//樹的重心近似是一個樹的中心位置 ,所以我們讓重心的大小盡可能等於該當前你所求節點大小的一半 
    	{
    		k=fa[k];//k就往上跳,不跳的時候說明找到了
		}
    	ans[u]=k;
	}
}
int main()
{
	cin>>n>>q;
	for(int i=2;i<=n;i++)
	{
		int x;
		cin>>x;
		fa[i]=x;
		tree[i].push_back(x);
		tree[x].push_back(i);
	}
	dfs(1,0);
	for(int i=1;i<=q;i++)
	{
	int x;
	cin>>x;
	cout<<ans[x]<<endl;
	}

}