最小化边缘删除以将 Tree 转换为大小最多为 N/2 的森林
给定一棵有N个节点的树,编号从0 到 N - 1,任务是找到最小的边删除数,这样,树就被转换为森林,其中森林中的每棵树的大小都可以小于等于为⌊N/2⌋。
例子:
Input: N = 3, edges = [[0, 1], [0, 2]]
0
/ \
1 2
Output: 2
Explanation: The maximum size of each tree after removing the edges can be 1.
So every node has to be separated from each other.
So, remove all the 2 edges present in the tree.
Hence, the answer will be 2.
Input: N = 7, edges = [[0, 1], [1, 2], [1, 3], [0, 4], [4, 5], [4, 6]]
0
/ \
1 4
/ \ / \
2 3 5 6
Output: 2
Explanation: Remove the edges (0 – 1) and (0 – 4) to satisfy the condition. Hence, the answer will be 2.
方法:解决问题的想法是使用 深度优先搜索。
请按照以下步骤解决给定问题:
- 从给定的输入创建图表。
- 使用dfs函数计算质心。
- 如果树有两个质心,那么答案将为 1。
- 否则,声明一个向量 subtreeSize,它将计算质心所有子节点的子树大小。
- 使用dfs2函数计算子树大小。
- 声明两个变量ans和sum来存储答案和由于删除边而删除的节点数。
- 按降序对 subtreeSize 进行排序。
- 迭代 subtreeSize 向量。
- 将当前值加到总和中,并将 ans 加 1。
- 如果剩余节点数小于等于N/2
- 打破循环。
- 最后,返回ans 。
以下是上述方法的实现:
C++
// C++ Code for the above approach:
#include
using namespace std;
// Function to calculate the
// Centroids of the tree.
void dfs(int n, int par,
vector* ar,
vector& size,
int& cent1, int& cent2,
int& some, int tot)
{
size[n] = 1;
int mx = 0;
// Iterate through the children
// of the current node and
// store the maximum of the subtree size
// among the children in the mx variable.
for (int child : ar[n]) {
if (child != par) {
dfs(child, n, ar, size,
cent1, cent2, some, tot);
size[n] += size[child];
mx = max(mx, size[child]);
}
}
mx = max(mx, tot - size[n]);
// If mx is smaller than the maximum
// subtree size till now,
// update that and centroids accordingly.
if (mx < some) {
some = mx;
cent1 = n;
cent2 = -1;
}
else if (mx == some) {
cent2 = n;
}
}
// Function to calculate the subtree
// size of the given node.
void dfs2(int n, int par,
vector* ar, int& val)
{
val++;
for (int child : ar[n]) {
if (child != par) {
dfs2(child, n, ar, val);
}
}
}
int minimumEdges(int n,
vector >& edges)
{
vector ar[n];
vector size(n, 0);
// Create the graph
// From the given input.
for (int i = 0; i < n - 1; i++) {
ar[edges[i][0]]
.push_back(edges[i][1]);
ar[edges[i][1]]
.push_back(edges[i][0]);
}
int cent1 = -1, cent2 = -1, some = 1000000;
// Calculate the centroids
// Using the dfs function.
dfs(0, -1, ar, size,
cent1, cent2, some, n);
// If the tree has two centroids,
// Then the answer will be 1.
if (cent2 != -1) {
return 1;
}
// Declare a vector subtreeSize,
// Which will calculate the
// Subtree size of all the children
// Of the centroid.
vector subtree_size;
// Calculate the subtree sizes
// Using the dfs2 function.
for (int x : ar[cent1]) {
int val = 0;
dfs2(x, cent1, ar, val);
subtree_size.push_back(val);
}
// Declare two variables, ans and sum,
// To store the answer
// And the number of nodes removed
// Due to the removal of edges.
int sum = 0;
int ans = 0;
// Sort the subtreeSize
// In descending order.
sort(subtree_size.rbegin(),
subtree_size.rend());
// Iterate over the “subtreeSize” vector.
for (int x : subtree_size) {
// Add the current value to the sum
// And increase the ans by 1.
sum += x;
ans++;
// If the remaining nodes are
// Less than or equal to N / 2,
// Break the loop.
if (n - sum <= n / 2) {
break;
}
}
// Finally, return the ans.
return ans;
}
// Driver code
int main()
{
int N = 3;
vector > edges
= { { 0, 1 }, { 0, 2 } };
cout << minimumEdges(N, edges) << "\n";
return 0;
}
2
时间复杂度: O(N * log(N))
辅助空间: O(N)