持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情
创建价值相同的连通块
有一棵 n 个节点的无向树,节点编号为 0 到 n - 1 。
给你一个长度为 n 下标从 0 开始的整数数组 nums ,其中 nums[i] 表示第 i 个节点的值。同时给你一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 ai 与 bi 之间有一条边。
你可以 删除 一些边,将这棵树分成几个连通块。一个连通块的 价值 定义为这个连通块中 所有 节点 i 对应的 nums[i] 之和。
你需要删除一些边,删除后得到的各个连通块的价值都相等。请返回你可以删除的边数 最多 为多少。
1 <= n <= 2 * 10^4nums.length == n1 <= nums[i] <= 50edges.length == n - 1edges[i].length == 20 <= edges[i][0], edges[i][1] <= n - 1edges表示一棵合法的树。
思路
题目要求我们删边,这个比较抽象,不好理解 举一个例子来说明问题:
对于下列树来说:
判断合法
代码
class Solution {
public:
vector<vector<int>> ve;
vector<int> g;
int cnt = 0;
int flag = false;
int now = 0;
int dfs(int u, int f) {
int sum = g[u];
if (!flag) return 0;
for (auto v : ve[u]) {
if (v == f) continue;
sum += dfs(v, u);
}
if (sum == now) {
if (f != -1) cnt ++;
return 0;
} else if (sum > now) {
flag = false;
return 0;
}
return sum;
}
int componentValue(vector<int>& nums, vector<vector<int>>& edges) {
int sum = 0;
ve.resize(nums.size());
g = nums;
for (auto v : edges) ve[v[0]].push_back(v[1]), ve[v[1]].push_back(v[0]);
for_each(begin(nums), end(nums), [&](int v) {sum += v;});
int ans = 0;
for (int i = 2; i <= nums.size(); i ++) {
if (sum % i != 0) continue;
now = sum / i;
cnt = 0;
flag = true;
dfs(0, -1);
if (flag) ans = max(ans, cnt);
}
return ans;
}
};