对于每个点,我们可以用一次dfs求出这个点到以这个点为字树的最远距离和次远距离;
然后用换根法再来一遍dfs求出这个点到除这个点子树之外的最远距离;
显然的,每次的询问我们可以用向上的最大值加向下的最大值得到;
具体换根法的实现可以看下面的代码~;
#include <bits/stdc++.h> #define inc(i,a,b) for(register int i=a;i<=b;i++) using namespace std; int head[200010],cnt; class littlestar{ public: int to;int nxt; void add(int u,int v){ to=v; nxt=head[u]; head[u]=cnt; } }star[200010]; template<class nT> inline void read(nT& x) { char c;while(c=getchar(),!isdigit(c));x=c^48; while(c=getchar(),isdigit(c)) x=x*10+c-48; } int n,m; int dep[100010],father[100010]; int f[100010],son1[100010],g[100010],son2[100010]; void dfs(int u,int fa) { dep[u]=dep[fa]+1; father[u]=fa; f[u]=1; for(int i=head[u];i;i=star[i].nxt){ int v=star[i].to; if(v==fa) continue; dfs(v,u); if(f[v]+1>f[u]){ son2[u]=son1[u]; g[u]=f[u]; son1[u]=v; f[u]=f[v]+1; } else if(f[v]+1>g[u]){ son2[u]=v; g[u]=f[v]+1; } } } int ftop[100010]; void dfs2(int u,int fa) { for(int i=head[u];i;i=star[i].nxt){ int v=star[i].to; if(v==fa) continue; if(v==son1[u]){ ftop[v]=max(ftop[u],g[u])+1; } else{ ftop[v]=max(ftop[u],f[u])+1; } dfs2(v,u); } } int main() { //freopen("olefin.in","r",stdin); //freopen("olefin.out","w",stdout); int gggg; read(gggg); int T; read(T); while(T--){ memset(head,0,sizeof(head)); memset(dep,0,sizeof(dep)); memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); memset(son1,0,sizeof(son1)); memset(ftop,0,sizeof(ftop)); cnt=0; read(n); read(m); inc(i,2,n){ int tmp;read(tmp); star[++cnt].add(tmp,i); } dfs(1,0); dfs2(1,0); inc(i,1,m){ int tmp;read(tmp); printf("%d ",f[tmp]+ftop[tmp]-2); } printf(" "); } }