J-绝妙的平衡_2024牛客寒假算法基础集训营6 (nowcoder.com)
题目大意
小红拿到了一棵有根树,其中有一些节点被染成了红色。树的根节点是 1 号节点。
小红希望你给每个节点的权值赋值为 1 或者 2,需要满足每个红色节点的子树节点权值之和为 3 的倍数。
请你给出任意一个赋值方案。
思路
首先 全是红色不行 因为只能赋值 1 或 2
那么在以一个红点为root的树中是什么样子呢?
假设先全部赋值为2
如果和取模后为1 比如只有两个点 (2+2)%3 = 1那么就让一个点变成1就好
2呢 就让那两个点变成1
所以只要满足至少有两个点 就可以满足情况
总结 我们需要做的就是找到所有以红点为root的子树遍历它有至少两个节点就可以了
代码
#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>
#include<queue>
#include<set>
#include<vector>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define long long
#define PI acos(-1.0)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int INF = 1e18 + 10;
const int N = 1e5 + 10;
const int M = 1e7 + 10;// 节点数量 3e6就够了是为什么?
const int mod = 1e9 + 7;
int n, m, k, x;
int qcal(int a, int b) { int res = 1; while (b) { if (b & 1) res = res * a % mod; b >>= 1; a = a * a % mod; } return res; }
string st;
bool is_prime(int n) { if (n < 2) return false; for (int i = 2; i <= n / i; i++) { if (n % i == 0) { return false; } }return true; }
vector<vector<int>> a(N);
bool ans = true;
int res[N];
void dfs(int now)
{
//需要统计这个以红为root的子树有多少个
vector<int> all;
all.push_back(now);
//假如儿子还有很多儿子 我们就需要用一个queue来遍历每一个当前红root的儿子
queue<int> q;
for(auto c:a[now]) q.push(c);// 已经存了待用的点了
// 现在的任务就是把他们遍历完
while(!q.empty())
{
int tmp = q.front();
q.pop();
if(st[tmp] == 'R')
{
dfs(tmp);
continue; // 遍历完就不需要遍历了 相当于删掉这颗子树
}
all.push_back(tmp);
for(auto c:a[tmp]) q.push(c); //一定不能忘记往下遍历 倘若都是白的 应该再往下找 只要放进队列就行
}
// 遍历完一棵以红节点为root的树之后我们需要检验
if(all.size() < 2)
{
ans = false;
return;
}
// 然后把每个节点赋值
if(all.size() % 2 == 1)
{
// cout << "SIZE: " << all.size() << endl;
res[all[0]] = res[all[1]] = res[all[2]] = 1; // 先让前三个点为1 因为至少有三个点 后面的12循环即可
for(int i = 3;i < all.size();i ++)
{
if(i % 2) res[all[i]] = 1;
else res[all[i]] = 2;
}
}
else
{
for(int i = 0;i < all.size();i ++)
{
if(i % 2) res[all[i]] = 1;
else res[all[i]] = 2;
}
}
}
void solve(int now)
{
// 如果当前这个点是R就dfs 搞完就删除
if(st[now] == 'R')
{
dfs(now);
}
// 如果不是 就把所有的儿子处理一下
for(auto c:a[now]) solve(c);
}
void gzy()
{
cin >> n >> st;
st = " " + st;
for(int i = 2;i <= n;i ++)
{
cin >> x;
a[x].push_back(i);
}
solve(1); // 从第一个点开始遍历
if(!ans)
{
cout << -1 << endl;
return;
}
// 对于一开始就是白色节点 他们暂时是没有被赋值的 所以需要全部让他们为一个值的
for(int i = 1;i <= n;i ++)
if(!res[i]) res[i] = 1;
for(int i = 1;i <= n;i ++) cout << res[i];
puts("");
}
signed main()
{
IOS;
int _ = 1;
while (_--) gzy();
return 0;
}
// /**
// * ┏┓ ┏┓+ +
// * ┏┛┻━━━┛┻┓ + +
// * ┃ ┃
// * ┃ ━ ┃ ++ + + +
// * ████━████+
// * ◥██◤ ◥██◤ +
// * ┃ ┻ ┃
// * ┃ ┃ + +
// * ┗━┓ ┏━┛
// * ┃ ┃ + + + +Code is far away from
// * ┃ ┃ + bug with the animal protecting
// * ┃ ┗━━━┓ 神兽保佑,代码无bug
// * ┃ ┣┓
// * ┃ ┏┛
// * ┗┓┓┏━┳┓┏┛ + + + +
// * ┃┫┫ ┃┫┫
// * ┗┻┛ ┗┻┛+ + + +
// */