消息传递
解题思路
一开始怎么觉得那么难,后来稍微一问mjt大佬怎么那么简单?
意思就是你选一个人进行消息传递,然后求最少时间。
所以每个点都有当根节点的机会,遍历根节点。
然后就是儿子节点的问题了,然后就用到了贪心思想。
因为你要先告诉花费时间长的呗,然后再告诉时间短的。
然后就是很简单的树形dp了,转移方程$$dp[u]=max(dp[u],dp[v]+i-1)$$
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int n;
struct edge
{
int next,to;
}e[2000];
int head[2000],tot,dp[2000],ins[2000];
void add(int x,int y){
e[++tot].next = head[x];
head[x] = tot;
e[tot].to = y;
}
bool cmp(int x,int y){
return x>y;
}
int minn=0x7fffffff,a[1001];
void dfs(int x,int f){
int b[550] = {0},cnt = 0;
for(int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(v==f)continue;
dfs(v,x);
b[++cnt]=dp[v];
}
sort(b+1,b+1+cnt,cmp);
for(int i=1;i<=cnt;i++)
dp[x]=max(dp[x],b[i]+i-1);
dp[x] += 1;
}
int main(){
scanf("%d",&n);
for(int i=2;i<=n;i++){
int a;
scanf("%d",&a);
add(a,i);
add(i,a);
}
for(int i=1;i<=n;i++){
memset(dp,0,sizeof(dp));
dfs(i,0);
minn=min(minn,dp[i]);
ins[i]=dp[i];
}
printf("%d
",minn);
for(int i=1;i<=n;i++)if(minn==ins[i])printf("%d ",i);
}