赞
踩
本题 DFS + 剪枝可过!!!
输入左儿子右儿子时如果遇到 − 1 -1 −1 就把它设为 0 0 0,这样好判断。
输入函数:
void inp() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &w[i]);
for(int i = 1; i <= n; ++i) {
scanf("%d%d", &le[i], &rt[i]);
if(le[i] == -1)
le[i] = 0;
if(rt[i] == -1)
rt[i] = 0;
}
}
然后计算出所有子树的结点个数,方便剪枝和更新答案:
void dfs1(int u) {
if(!u)
return;
dfs1(le[u]);
dfs1(rt[u]);
cnt[u] = cnt[le[u]] + cnt[rt[u]] + 1;
}
然后就是计算答案了,我们先写一个函数 bool check(int u, int v)
,就是判断以
u
u
u 结点为根结点的子树和以
v
v
v 结点为根结点的子树是否对称,这里有很多剪枝,但都很简单,相信大家都能看懂:
void bemax(int &a, int b) { a = a > b ? a : b; } bool check(int u, int v) { if(!u && !v) return true; if(!u || !v) return false; if(w[u] != w[v]) return false; if(cnt[u] != cnt[v]) return false; return check(le[u], rt[v]) & check(rt[u], le[v]); }
有了这个函数,就很好计算答案了:
void dfs2(int u) {
if(!u)
return;
if(check(le[u], rt[u]))
bemax(ans, cnt[u]);
dfs2(le[u]);
dfs2(rt[u]);
}
最后再输出一下 a n s ans ans 就可以了,这样我们就 A(shui)掉了此题。
#include <cstdio> using namespace std; const int N = 1e6 + 5; int n; int w[N]; int le[N], rt[N]; int cnt[N]; int ans; void bemax(int &a, int b) { a = a > b ? a : b; } bool check(int u, int v) { if(!u && !v) return true; if(!u || !v) return false; if(w[u] != w[v]) return false; if(cnt[u] != cnt[v]) return false; return check(le[u], rt[v]) & check(rt[u], le[v]); } void dfs1(int u) { if(!u) return; dfs1(le[u]); dfs1(rt[u]); cnt[u] = cnt[le[u]] + cnt[rt[u]] + 1; } void dfs2(int u) { if(!u) return; if(check(le[u], rt[u])) bemax(ans, cnt[u]); dfs2(le[u]); dfs2(rt[u]); } void inp() { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &w[i]); for(int i = 1; i <= n; ++i) { scanf("%d%d", &le[i], &rt[i]); if(le[i] == -1) le[i] = 0; if(rt[i] == -1) rt[i] = 0; } } void work() { dfs1(1); dfs2(1); printf("%d\n", ans); } int main() { inp(); work(); return 0; }
如果这篇博客对您(您的团队)有帮助的话,就帮忙点个赞,加个关注!
最后,祝您(您的团队)在 OI 的路上一路顺风!!!
┬┴┬┴┤・ω・)ノ ByeBye
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。