(纪中)3501. 消息传递)(news)【树形DP】

66 篇文章 1 订阅
20 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路

首先可以想到暴力每一个点作为根,求最小的传递时间。
设f[i]表示某点以i号边连向的子树中所有节点都被传递到消息的最短时间。易得:
在这里插入图片描述
考虑贪心,让 f i f_i fi的孩子中消耗时间最大的先被传递,所以我们可以把 f j f_j fj从大到小排序, o r d e r order order表示f_j在序列中排在第几位(因为要依次传给每个儿子),这样 f j + o r d e r j f_j+order_j fj+orderj就表示爸爸以 j j j这条边连向的子树全部被传递所需时间,这样 f i f_i fi f j f_j fj中最大值,也是一个恒定的值。求出f_i后返回值给他的爸爸,他的爸爸得到了他所有儿子的消耗时间,把消耗时间排序…接着按照以上的思路。。

讲的好像不是很清楚啊, s o r r y sorry sorry


代码

#pragma GCC optimize("3")
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<queue>
using namespace std;

int n,x,k,ans,t,w[200010],head[200010],p[200010],f[200010];

struct c{
	int x,next;
}a[400010];

void add(int x,int y){
	a[++k].x=y;
	a[k].next=head[x];
	head[x]=k;
}

int dfs(int x,int fa,int v){
	if(f[v]&&v)return f[v];
	int res=0;
	priority_queue<int>q;
	for(int i=head[x];i;i=a[i].next)
	{
		int y=a[i].x;
		if(y!=fa)
		q.push(dfs(y,x,i));//从大到小排序
	}
	for(int i=1;!q.empty();q.pop(),i++)
		res=max(res,q.top()+i);//计算消耗时间并求max
	return f[v]=res;
}

int main(){
	freopen("news.in","r",stdin);
    freopen("news.out","w",stdout);
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
    	scanf("%d",&x);
    	add(i,x);add(x,i);
	}
	ans=2137383600;
	for(int i=1;i<=n;i++)
	{
		p[i]=dfs(i,0,0)+1;
		if(p[i]<ans)
			ans=p[i];
	}
	printf("%d\n",ans);
	for(int i=1;i<=n;i++)
		if(p[i]==ans)
			printf("%d ",i);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值