题意

给你一棵树,你需要找到它的一颗子树满足以下条件
1.是一棵二叉树
2.这棵树的所有节点的左右儿子交换位置,交换后新树和原树的结构及每个位置的点权没变。

分析

先预处理出每棵子树的大小,然后枚举以任意节点为子树的根。递归处理这棵树的正确性。当这个节点没有儿子直接返回。当有两个儿子且两个儿子的权相同时,递归这两个儿子的儿子就可以了。

代码

#include<bits/stdc++.h>
#define ll long long
const int N=1e6+5,INF=0x3f3f3f3f,mod=998244353;
using namespace std;

int n;
int val[N],son[N][2],size_[N];

inline int read()
{
    register int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}

bool check(int u,int v)
{
    if(u==-1&&v==-1)
        return true;
    if(u!=-1&&v!=-1)
     if(val[u]==val[v])
      if(check(son[u][0],son[v][1])&&check(son[u][1],son[v][0]))
        return true;
    return false;
}

void dfs(int u)
{
    size_[u]=1;
    if(son[u][0]!=-1)
    {
        dfs(son[u][0]);
        size_[u]+=size_[son[u][0]];
    }
    if(son[u][1]!=-1)
    {
        dfs(son[u][1]);
        size_[u]+=size_[son[u][1]];
    }
    return ;
}

int main()
{
    n=read();
    for(int i=1;i<=n;i++)    val[i]=read();
    for(int i=1;i<=n;i++)    son[i][0]=read(),son[i][1]=read();
    dfs(1);
    int ans=0;
    for(int i=1;i<=n;i++)
     if(check(son[i][0],son[i][1]))
      ans=max(ans,size_[i]);
    printf("%d",ans);
    return 0;
}