[题解] (lgP5018)
题目链接
大体思路
(2018)年不会做这道题,(2020)年了还是不会…
这个题有很多不同的思路,比如:暴力(dfs),或者中序遍历之后(manacher),又比如接下来介绍的树形(DP)的方法。
这里实际上并不是严格的(DP),只是类似与树形(DP)的思想,实际上是用深搜来实现的。
因为实际上就是要求出一个完全对称的二叉树,所以我们可以兵分两路,从左子树和右子树一起来判断,然后直接枚举答案。
代码
#include <bits/stdc++.h>
using namespace std;
int l[1000010],r[1000010],val[1000010],maxx = 1,sum = 1;
bool judge(int x,int y){//判断以x为根的子树和以y为根的子树是否对称
if(x == -1 && y == -1 && val[x] == val[y])return true;//两个都是叶子节点并且权值相等就对称
if(x == -1 || y == -1 || val[x] != val[y])return false;//如果两个节点中只有一个是叶子节点那么子树结构不对称,或者是两个点的权值不一样
sum += 2;//累加答案
return (judge(l[x],r[y])) && (judge(l[y],r[x]));//因为是求对称的二叉树所以两条最外面的“树枝”,和两条被夹在中间的“树枝”都要对称。
}
int main(){
int n;
cin>>n;
for(int i = 1;i <= n;i++)cin>>val[i];
for(int i = 1;i <= n;i++)
cin>>l[i]>>r[i];
for(int i = 1;i <= n;i++){//暴力枚举答案
sum = 1;
if(judge(l[i],r[i]) && sum > maxx){
maxx = sum;
}
}
cout<<maxx<<endl;
return 0;
}