春招模拟赛第七场|阿里巴巴|2023.04.12研发岗笔试
- Status
- Done
- Rule
- IOI
- Problem
- 3
- Start at
- 2023-4-18 19:00
- End at
- 2023-4-18 20:20
- Duration
- 1.3 hour(s)
- Host
- Partic.
- 74
You cannot submit for this problem because the contest is ended. You can click "Open in Problem Set" to view this problem in normal mode.
第一遍dfs求解这棵树上每个子树的大小sz[i]以及每个子树中红色结点的个数r[i] . 我们假设1为根节点
第二遍dfs,枚举每条边(u,v),考虑将这条边删掉之后,子树的红色结点个数为r[v] , 蓝色结点个数就是sz[v]−r[v]. 另一个颗树的红色结点个数就是r[1]−r[v] . 蓝色结点个数就是sz[1]−r[1]−(sz[v]−r[v])
判断一下是不是都 红色 > 蓝色即可
P1170 2023.04.08-美团春招-第五题-RGB树
#include<bits/stdc++.h>
using namespace std;
const int maxn =1e5 + 5;
string a;
// 矢量版邻接矩阵 , 存每个点的邻接点
vector<int> e[maxn];
// sz , r 含义如上
int sz[maxn] , r[maxn];
// 第一遍 dfs 求出每个点的 sz 和 r
void dfs1 (int u , int fa){
sz[u] = 1;
r[u] = a[u] == 'R';
for (auto v : e[u]){
if (v == fa) continue;
dfs1(v , u);
sz[u] += sz[v];
r[u] += r[v];
}
return ;
}
// 第二遍 枚举每条边(u,v)
int ans = 0;
void dfs2 (int u , int fa){
for (auto v : e[u]){
if (v == fa) continue;
dfs2(v , u);
// 判断子树是否合法
if (r[v] <= sz[v] - r[v]) continue;
// 判断主树是否合法
int rest_sz = sz[1] - sz[v];
int rest_r = r[1] - r[v];
if (rest_r <= rest_sz - rest_r) continue;
// 都合法,则这条边可以,答案 + 1
ans++;
}
return ;
}
int main (){
int n;
cin >> n;
cin >> a;
// 读入
a = '#' + a;
for (int i = 1 ; i < n ; i++){
int x , y;
cin >> x >> y;
e[x].push_back(y);
e[y].push_back(x);
}
dfs1(1 , -1);
dfs2(1 , -1);
cout << ans << endl;
return 0;
}
曾经有一个叫做小红的年轻人,他是一个热衷于研究二叉树的数学家。他认为,一棵树只有当它的红色节点数量大于蓝色节点数量时才是好树。他的定义引起了人们的热议,有些人同意他的定义,有些人则持不同意见。但无论怎样,这个定义还是被广泛地接受了。
有一天,小红发现了一棵好树,但他觉得它不够完美。于是他开始思考,如果能够将这棵好树分成两个好树,那它就更加完美了。
经过一番研究,他发现只需要删除一条边,就可以将这棵树分成两个好树。他想知道有多少种删除边的方案,于是他向你求助。
第一行输入一个正整数 n ,代表节点的数量。
第二行输入一个长度为 n 的,仅包含 'R' 和 'B' 两种字符的字符串,第 i 个字符为 'R' 代表第 i 个节点被染成红色,'B'代表被染成蓝色。
接下来的 n−1 行,每行输入两个正整数 u 和 v ,代表节点 u 和节点 v 有一条边连接。
1≤n≤105
一个整数,代表删边的方案数。
输入
5
RRBRB
1 2
2 3
1 4
4 5
输出
0
样例解释
无论删除哪条边,都会导致有一个子树不是好树。