首页 > 其他分享 >P2018:消息传递题解——二次扫描与换根

P2018:消息传递题解——二次扫描与换根

时间:2022-12-10 16:22:05浏览次数:70  
标签:head P2018 int 题解 Rank fa 消息传递 上级 ver

消息传递

题面

题目描述

巴蜀国的社会等级森严,除了国王之外,每个人均有且只有一个直接上级,当然国王没有上级。如果A是B的上级,B是C的上级,那么A就是C的上级。绝对不会出现这样的关系:A是B的上级,B也是A的上级。

最开始的时刻是0,你要做的就是用1单位的时间把一个消息告诉某一个人,让他们自行散布消息。在任意一个时间单位中,任何一个已经接到消息的人,都可以把消息告诉他的一个直接上级或者直接下属。

现在,你想知道:

1.到底需要多长时间,消息才能传遍整个巴蜀国的所有人?

2.要使消息在传递过程中消耗的时间最短,可供选择的人有那些?

输入格式

输入文件的第一行为一个整数N(N≤1000),表示巴蜀国人的总数,假如人按照1到n编上了号码,国王的编号是1。第2行到第N行(共N-1行),每一行一个整数,第i行的整数表示编号为i的人直接上级的编号。

输出格式

文件输出共计两行:

第一行为一个整数,表示最后一个人接到消息的最早时间。

第二行有若干个数,表示可供选择人的编号,按照编号从小到大的顺序输出,中间用空格分开。

样例 #1

样例输入 #1

8
1
1
3
4
4
4
3

样例输出 #1

5
3 4 5 6 7

题解

题意简述:给定一棵树,其中1是树根,要找到一个点将其染色,耗费1的时间,然后在每一个时间内,所有被染色点可以在与其相连的点中选择一个染色,将整棵树都被染完的时间即为这个点的答案。要求出最小的答案,并且指出哪些点的答案最优。
对于此类问题,我们先来思考如果指定了一个点如何求出答案。

首先明确,由于一个点可以向上向下传递,那么此时谁是父亲谁是儿子不重要了,我们只需要知道与这个点连边的点可以被这个点染色即可,那么我们可以将这个点变为树根,显然此时只能向下传递,此时这个问题就很像一个树形DP了,具体的,设\(f[x]\)表示将\(x\)染色后染完整个\(x\)的子树的最小时间(为了方便计算,这里没有将选择\(x\)的“1”计入,当然最后将答案加一即可)。那么参考这个中关于贪心的证明部分,容易知道:

\[f[x]=\max_{y\in son(x)}\lbrace f[y]+Rank_{y}\rbrace \]

其中\(son(x)\)代表\(x\)的子节点集合,\(Rank_y\)是指在\(x\)的所有儿子节点中\(f\)值的排名(从大到小)。\(O(n\log_2 n)\)DP即可求解,这个上界很松,故其实\(O(n^2\log_2n)\)的枚举即可AC。

但显然,进行\(n\)次DP肯定有优化的空间。考虑二次扫描与换根法,请看这图:

对于这部分的计算,可以设\(g[x]\)表示在\(father(x)\)为根的树(整棵树)中,除了以\(x\)为根的子树的答案,对于这个的计算,可以类比\(f\),也很简单:

\[g[x]=\max\lbrace g[fa(x)]+Rank_{fa(x)},\max_{y\in son(x)}\lbrace f[y]+Rank_y\rbrace\rbrace \]

其中\(fa\)表示父节点,\(Rank\)表示将所有的\(f[y](y\in son(x))\)与\(g[fa(x)]\)放在一起从大到小排序后的排名。

有了\(g\),\(ans[x]\)也就呼之欲出了:

\[ans[x]=1+\max\lbrace g[x]+Rank_x,\max_{y\in son(x)}\lbrace f[y]+Rank_y\rbrace\rbrace \]

\(Rank\)含义类似。

进行两次DP即可求出解,需要注意的是,对于根节点\(1\),不存在\(g\),也不计入子节点统计\(g\)的\(g[fa(x)]\)。

加一的原因是无论是\(f[x],g[x]\)都是默认\(x\)已染色,但实际上需要1的时间将其染色。

#define N 2005
int head[N],nxt[N],ver[N],tot=1,f[N],g[N],ans[N],b[N],lst[N],n;
void add(int u,int v){
	nxt[++tot]=head[u],ver[head[u]=tot]=v;
}
void dfs1(int u,int fa){
	int cnt=0;
	lst[u]=fa;
	for(int i=head[u];i;i=nxt[i]){
		int v=ver[i];
		if(v==fa)continue;
		dfs1(v,u);
	}
	for(int i=head[u];i;i=nxt[i]){
		if(ver[i]==fa)continue;
		b[++cnt]=f[ver[i]];
	}
	sort(b+1,b+cnt+1);
	reverse(b+1,b+cnt+1);
	for(int i=1;i<=cnt;i++){
		f[u]=max(f[u],b[i]+i);
	}
}
void dfs2(int u,int fa){
	int cnt=0;
	if(fa!=1)b[++cnt]=g[fa];
	for(int i=head[fa];i;i=nxt[i]){
		int v=ver[i];
		if(v==u||v==lst[fa])continue;
		b[++cnt]=f[v];	
	}
	sort(b+1,b+cnt+1);
	reverse(b+1,b+cnt+1);
	for(int i=1;i<=cnt;i++){
		g[u]=max(g[u],b[i]+i);
	}
	cnt=1;b[1]=g[u];
	for(int i=head[u];i;i=nxt[i]){
		int v=ver[i];
		if(v==fa)continue;
		b[++cnt]=f[v];
	}
	sort(b+1,b+cnt+1);
	reverse(b+1,b+cnt+1);
	for(int i=1;i<=cnt;i++){
		ans[u]=max(ans[u],b[i]+i);
	}
	for(int i=head[u];i;i=nxt[i]){
		int v=ver[i];
		if(v==fa)continue;
		dfs2(v,u);
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=2;i<=n;i++){
		int v;
		cin>>v;
		add(i,v);add(v,i);
	}
	dfs1(1,0);
	ans[1]=f[1];
	for(int i=head[1];i;i=nxt[i]){
		int v=ver[i];
		dfs2(v,1);
	}
	int Ans=0x3f3f3f3f;
	for(int i=1;i<=n;i++)Ans=min(Ans,++ans[i]);
	cout<<Ans<<endl;
	for(int i=1;i<=n;i++)if(ans[i]==Ans)cout<<i<<" ";
}

标签:head,P2018,int,题解,Rank,fa,消息传递,上级,ver
From: https://www.cnblogs.com/oierpyt/p/16971776.html

相关文章

  • FJ的农场 题解
    原题见P4216首先\(\Theta(mn)\)暴力能够拿到\(30\)分,这个没有什么难度,可以参照一下我用来测试的暴力Link。首先让我们来简化一下题意:插入操作(即"\(Grow\)"),将树......
  • AcWing2437. Splay 题解
    题目大意:splay执行区间翻转示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e5+5;intn,m;structNode{ints[2],p,v;intsz,flag......
  • 洛谷P8767 [蓝桥杯 2021 国 A] 冰山 题解 splay tree
    题目链接:​​https://www.luogu.com.cn/problem/P8767​​鸣谢:这道题的顺利解决得到了​​7KByte​​大佬的大力帮助,在此再次表示感谢。首先,我的想法是这样的:使用一个spl......
  • 【题解】P8866 [NOIP2022] 喵了个喵(构造,adhoc)
    【题解】P8866[NOIP2022]喵了个喵题目链接P8866[NOIP2022]喵了个喵题意概述有一个牌堆和\(n\)个可以从栈底删除元素的栈,任务是要通过规则将所有的卡牌消去。开......
  • #yyds干货盘点#按钮点击重复提交问题解决
    提交按钮重复点击这是最常见的问题,重复提交会造成多条数据入库。点击提交给个loading提示过渡,期间按钮不可再次触发就可以。​查询按钮重复点击如果查询按钮点一下就设置loa......
  • 题解 CF1713F【Lost Array】
    首先,为了方便将第\(1\)行的数从右往左重标号为\(0,1,\cdots,n-1\)。我们发现\((1,i)\)对于\((j,n+1)\)的贡献是\(C(i+j,i)\pmod2\),根据\(\text{lucas}......
  • P8377 [PFOI Round1] 暴龙的火锅 题解
    题目传送门题目背景暴龙爱吃火锅。题目描述定义\(S(x)\)表示\(x\)的每一位的数字之和,例如:\(S(14)=1+4=5\),\(S(114514)=1+1+4+5+1+4=16.\)另外,定义\(fib(x)\)代......
  • CF1458C 题解
    题意传送门\(T\)组测试数据,每次给一个\(n\timesn\)的矩阵,每行每列都是个\(1\ton\)的排列。有\(m\)次操作,如果是UDLR就是要把整个矩阵每行/每列往一个方向循环......
  • 当远程设备或者计算机不接受连接 问题解决
    远程设备或计算机不接受连接问题解决tmd一大中午打开电脑发现没网手机却有网给电脑连上热点也不行真tmd晦气解决方法这三个东西都勾选取消 ......
  • CF1218G Alpha planetary system 题解
    Part1设\(w_x\)表示点\(x\)的权值\(\bmod3\),\(c_x\)表示\(x\)的所属集合编号(\(c_x\in\{0,1,2\}\)),\(v_i\)表示第\(i\)条边的权值。一个直接的想法是使所有......