消息传递

传送门

消息传递

解题思路

一开始怎么觉得那么难,后来稍微一问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\n",minn);
    for(int i=1;i<=n;i++)if(minn==ins[i])printf("%d ",i);
}
posted @ 2018-09-13 09:41  _Lancy  阅读(378)  评论(0编辑  收藏  举报