根据样例建树:
举个简单的例子 送餐地点是 5,6,4
可以分成 先送四->返回外卖站->送5 6 或 先送 5 6->返回外卖站 ->送 4 的两种方案的选择。
转换一下就变成 送 5 6 回 外卖站 + 送 4 回外卖站 - 回外卖站的最长路程
送 5 6 回外卖站的路程 的计算如下
依次遍历 5 6
每向上一次 路程+2(往返两次)
计算6时 ,5和6最近公共祖先以上的路程不用计算,可以用s数组标记。
代码如下:
#include<bits/stdc++.h>
#define N 100010
using namespace std;
int fa[N],h[N],s[N];
int n,m,root;
int ans;
int cnti(int x)
{
if(h[x]!=0) return h[x];
h[x]=cnti(fa[x])+1;
return h[x];
}
void add(int x)
{
if(s[x]) return;
ans+=2;
s[x]=1;
add(fa[x]);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>fa[i];
if(fa[i]==-1) root=i;
}
h[root]=1;
for(int i=1;i<=n;i++)
{
if(h[i]==0) cnti(i);
}
int maxh=1,k;
s[root]=1;
while(m--)
{
cin>>k;
maxh=max(maxh,h[k]);
add(k);
cout<<ans-maxh+1<<endl;
}
return 0;
}