参考原文链接:
笔者也是初学者,本文是在参考文章的基础上根据自己理解写得注释版,希望能给有需要的童鞋一些帮助,少走我的弯路~
#include<bits/stdc++.h>
using namespace std;
const int N = 100006;
set<int>st;
int edge[N];//N结点的父亲
int max_length = 0;
int dis[N];//N结点的深度
int dfs(int cur, int len)//返回 2* (总相关结点之间的线段数)
{
if(st.count(cur))//返回出现次数0 / 1=>cur结点已经被访问过了
{
max_length = max(max_length, dis[cur] + len);
//若新考虑的结点(记为A)的深度为所有需要的送餐到的结点中最大的,则取dis[cur] + len,
//此时的cur为经过多次递归后的, 找到的已经在st中(即曾经已经访问过的)的结点,
// dis[cur]即他的深度, 加上len后即A的深度
return 2* len;
}
int res = dfs(edge[cur], len+1);//递归,往上找父节点,直到找到已经被访问过的(加入set中)
st.insert(cur);//在递归的过程中,将访问到的结点都记忆到set中
dis[cur] = dis[edge[cur]] + 1;//本递归中的cur结点对应深度 = 其父亲深度 + 1
return res;//返回上一层递归,可见, 到第一层递归时,res的值和最后一层返回的res值是相等的
}
int main()
{
int n, m;
cin>>n>>m;
for(int i=1; i<=n; i++)
{
cin>>edge[i];
if(edge[i] == -1)
{
st.insert(i);//将根节点计入set
dis[i] = 0;//根节点深度为 0
}
}
int ans = 0;//2*总相关结点之间的线段数
for(int i=1; i<=m; i++)
{
int d;
cin>>d;// (在set中)
ans += dfs(d, 0);//在考虑到前面访问的所有结点的基础上, 补充上从d结点到距离d最近的 且已经被访问过的结点的距离的两倍 => 2*总相关结点之间的线段数
cout<< ans - max_length << endl;//2*总相关结点之间的线段数 - 最大深度
}
return 0;
}
😋ღ ʕ̡̢̡•̫͡•ʔ̢̡̢ ღ😋
~ 如果还有问题可以留言,咱们一起讨论,一起进步 ~ 希望对你有帮助 ~