2021.7.13【提高B组模拟2】T1 消息传递(记忆化搜索)(70分)(P2018 AC)

消息传递

题目传送门

题目大意(自己概括的)

每个人只有一个上司

你可以将一件消息告诉其中一个人(告诉他也有1个单位时间),那个人每个单位时间只能告诉自己的上司或一个员工

最后一个人知道的时间最早是多少,可以从哪些人开始(从小到大)

输入样例

8
1
1
3
4
4
4
3

输出样例

5
3 4 5 6 7

解题思路

枚举每个节点为起点

从它最大的子节点往下找

记得记忆化搜索

注意:
洛谷P2018 可 AC
gmoj 只有70

代码

#include<iostream>
#include<cstring>//gmoj必要用
#include<cstdio>
#include<queue>
using namespace std;
int n,tot,mmin=0x3f3f3f3f,b[2000005],f[4000005],head[2000005];
struct node
{
	int to,next;
}a[4000005];
void add(int x,int y)
{
	a[++tot]=(node){y,head[x]};
	head[x]=tot;
}
int dfs(int x,int fa,int bian)
{
	if(bian&&f[bian])return f[bian];//记忆化
	priority_queue<int> q;//堆
	for(int i=head[x];i;i=a[i].next)//枚举每条边
	{
		int y=a[i].to;
	 	if(y!=fa)
		 q.push(dfs(y,x,i));
	}
	int ans=0;
	for(int i=1;!q.empty();i++,q.pop())
	 ans=max(ans,q.top()+i);
	return f[bian]=ans;
}
int main()
{
	freopen("news.in","r",stdin);
	freopen("news.out","w",stdout);
	scanf("%d",&n);
	for(int i=2;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		add(x,i);add(i,x);//建边
	}
	for(int i=1;i<=n;i++)
	{
		b[i]=dfs(i,0,0)+1;//记忆化
		mmin=min(mmin,b[i]);
	}
	printf("%d\n",mmin);
	for(int i=1;i<=n;i++)
	 if(b[i]==mmin)printf("%d ",i);
	return 0;
}

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值