【题解】对称二叉树
数的同构
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。


一般情况(树hash):
https://blog.csdn.net/dpppbr/article/details/52915576
递归判断(用于二叉树):
https://www.cnblogs.com/jingjing1234/p/10822040.html
回归本题
其实就是多考虑了一下节点的顺序问题而已。
法一.
枚举根节点,递归判断是否对称。
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),n是枚举,logn是check函数。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, cost[N], l[N], r[N], con[N], root, ans;
bool vis[N];
void dfs(int x) {
if (!x)
return;
dfs(l[x]), dfs(r[x]);
con[x] = con[l[x]] + con[r[x]] + 1;
}
bool check(int x, int y) {
if (!x && !y)
return 1;
if (!x || !y)
return 0;
if (cost[x] != cost[y])
return 0;
if (check(l[x], r[y]) && check(r[x], l[y]))
return 1;
}
int main() {
// freopen("tree.in","r",stdin);
// freopen("tree.out","w",stdout);
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &cost[i]);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &l[i], &r[i]);
if (l[i] == -1)
l[i] = 0;
if (r[i] == -1)
r[i] = 0;
vis[l[i]] = vis[r[i]] = 1;
}
for (int i = 1; i <= n; i++)
if (!vis[i]) {
root = i;
break;
}
dfs(root);
for (int i = 1; i <= n; i++)
if (check(l[i], r[i]))
ans = max(ans, con[i]);
printf("%d", ans);
}
法二.
显然可以直接hash树的形态,即分中序遍历1(先进左子树)和中序遍历2(先进右子树)记录hash值,对于每一个节点,若是此节点的左儿子的中序遍历1的hash值等于右儿子的中续遍历2的hash值,说明这个点为根的树是对称的。
由于要考虑顺序,所以这里直接乘系数,不平方。
h
a
s
h
[
x
]
=
h
a
s
h
[
l
[
x
]
]
∗
V
1
+
c
o
s
t
[
x
]
∗
V
2
+
h
a
s
h
[
r
[
x
]
]
∗
V
3
;
hash[x]=hash[l[x]]*V1+cost[x]*V2+hash[r[x]]*V3;
hash[x]=hash[l[x]]∗V1+cost[x]∗V2+hash[r[x]]∗V3;
H
a
s
h
[
x
]
=
H
a
s
h
[
r
[
x
]
]
∗
V
1
+
c
o
s
t
[
x
]
∗
V
2
+
H
a
s
h
[
l
[
x
]
]
∗
V
3
;
Hash[x]=Hash[r[x]]*V1+cost[x]*V2+Hash[l[x]]*V3;
Hash[x]=Hash[r[x]]∗V1+cost[x]∗V2+Hash[l[x]]∗V3;
实测88pts,运气好的话,像下面这个代码,可以ac。这个方法不建议用。
其实我也没打出来
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define llg long long
#define maxn 1000100
#define V1 (llg)(999999751)
#define V2 (llg)(299999827)
#define V3 (llg)(100000007)
#define md (llg)(89999794200117649)
#define mdd (llg)(999999786000011449)
#define yyj(a) freopen(a ".in", "r", stdin), freopen(a ".out", "w", stdout);
inline llg getint() {
llg w = 0, q = 0;
char c = getchar();
while ((c < '0' || c > '9') && c != '-') c = getchar();
if (c == '-')
q = 1, c = getchar();
while (c >= '0' && c <= '9') w = w * 10 + c - '0', c = getchar();
return q ? -w : w;
}
unsigned long long hal[maxn], har[maxn], Har[maxn], Hal[maxn];
llg val[maxn], n, ans, he[maxn], lson[maxn], rson[maxn];
void dfs(llg x, llg fa) {
if (lson[x])
dfs(lson[x], x);
if (rson[x])
dfs(rson[x], x);
he[x] = he[lson[x]] + he[rson[x]] + 1;
if (he[lson[x]] == he[rson[x]] && hal[lson[x]] == har[rson[x]] && Hal[lson[x]] == Har[rson[x]]) {
ans = max(ans, he[x]);
}
hal[x] = hal[lson[x]] * V1 + val[x] * V2 + hal[rson[x]] * V3;
Hal[x] = Hal[lson[x]] * V1 + val[x] * V2 + Hal[rson[x]] * V3;
hal[x] %= md;
Hal[x] %= mdd;
har[x] = har[rson[x]] * V1 + val[x] * V2 + har[lson[x]] * V3;
Har[x] = Har[rson[x]] * V1 + val[x] * V2 + Har[lson[x]] * V3;
har[x] %= md;
Har[x] %= mdd;
}
int main() {
// yyj("D");
cin >> n;
for (llg i = 1; i <= n; i++) val[i] = getint();
for (llg i = 1; i <= n; i++) {
llg x = getint(), y = getint();
if (x != -1)
lson[i] = x;
if (y != -1)
rson[i] = y;
}
dfs(1, -1);
cout << ans;
return 0;
}

浙公网安备 33010602011771号