题目链接:https://www.luogu.org/problemnew/show/P5018

花絮:这道题真的比历年的t4都简单的多呀,而且本蒟蒻做得出t4做不出t3呜呜呜。。。

这道题可以是一只披着狼皮的羊了,全篇字字不离树,二叉树,然鹅却只需要会搜索就能解决。

在前些日子复习的时候并没有考虑的普及组会出于数据结构有关的题目,于是大多数时间只是放在搜索,模拟,简单dp上,只为了以防不测练了个dijkstra模板,考试时看到了这题果断骗分,结果敲完后去了趟厕所才发现搜索跑个‘暴力’也行啊,至少即便T了也多A几个点。

写到只剩30分钟是才过了全部样例,测了两三个卡自己的也过了,于是转颓T3,居然发现把30分的骗分写炸了。。。

下面进入正题。

分析:

考虑到我们可以从节点1(即树根开始搜索),dfs,搜到一个点先判断它存不存在,如果存在,先把他的两个子节点都搜上。然后开个c数组记录当前最大的节点数,当然权值也要累加,为了之后作为判断条件之一,然后我们尝试用c[i]更新答案,条件是必须大于当前答案,并且两个子节点形成对称,即可。主题思路已经讲出,接下来在代码中注释。

代码:

#include<cstdio>
using namespace std;
int v[1000005],ch[1000005][2],c[1000005],n,ans;
bool same(int a,int b)//判断两节点是否对称
{
	if(a==b)return 1;
	if(!a||!b)return 0;
	return v[a]==v[b]&&same(ch[a][1],ch[b][2])&&same(ch[a][2],ch[b][1]);
}
void dfs(int i)//大法师搜索
{
	if(!i)return;
	dfs(ch[i][1]);
	dfs(ch[i][2]);
	c[i]=1+c[ch[i][1]]+c[ch[i][2]];
	v[i]=v[i]+v[ch[i][1]]+v[ch[i][2]];
	if(ans<c[i]&&same(ch[i][1],ch[i][2]))ans=c[i];
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&v[i]);
	v[0]=1005;
	for(int i=1;i<=n;i++)
		for(int k=1;k<=2;++k)
		{
			scanf("%d",&ch[i][k]);
			if(ch[i][k]==-1)ch[i][k]=0;//清为0,好判断
		}
	dfs(1);
	printf("%d",ans);
	return 0;//the end
}
~完结✿✿ヽ(°▽°)ノ✿

注:此代码并非蒟蒻考场所写