【题解】对称二叉树

数的同构

给定两棵树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) Onlogn,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; }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530401.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(5)  评论(0编辑  收藏  举报  
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示