烯烃(olefin) 题解

题面

对于每个点,我们可以用一次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("
");
	}
}
原文地址:https://www.cnblogs.com/kamimxr/p/11806692.html