Linux 驅動框架---input子系統
阿新 • • 發佈:2020-09-06
這道題我用的是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; } }