具有 N 个节点和 N-1 条边的树为其节点提供了 2 种不同的颜色。
找到色差最小的子树,即 abs(1-color nodes – 2-colour nodes) 最小。
例子:
Input :
Edges : 1 2
1 3
2 4
3 5
Colours : 1 1 2 2 1 [1-based indexing where
index denotes the node]
Output : 2
Explanation : The sub-tree {1-2} and {1-2-3-5}
have color difference of 2. Sub-tree {1-2} has two
1-colour nodes and zero 2-colour nodes. So, color
difference is 2. Sub-tree {1-2-3-5} has three 1-colour
nodes and one 2-colour nodes. So color diff = 2.
方法 1:可以通过检查树的每个节点的每个可能的子树来解决问题。这将花费指数时间,因为我们将检查每个节点的子树。
方法 2:(高效)如果我们观察,我们正在多次求解树的一部分。这会产生重复出现的子问题。我们可以使用动态规划方法在一次遍历中获得最小的色差。为了让事情更简单,我们可以将颜色值设置为 1 和 -1。现在,如果我们有一个两个颜色节点相等的子树,我们的颜色总和将为 0。为了获得最小差异,我们应该有最大的负和或最大的正和。
- 案例 1当我们需要一个具有最大 sum 的子树时:如果它的值 > 0,我们就取一个节点,即 sum(parent) += max(0, sum(child))
- 案例 2当我们需要一个具有最小总和(或最大负总和)的子树时:如果它的值 < 0,我们就取一个节点,即 sum(parent) += min(0, sum(child))
为了得到最小和,我们可以交换节点的颜色,即-1变成1,反之亦然。
下面是实现:
C++
// CPP code to find the sub-tree with minimum color
// difference in a 2-coloured tree
#include
using namespace std;
// Tree traversal to compute minimum difference
void dfs(int node, int parent, vector tree[],
int colour[], int answer[])
{
// Initial min difference is the color of node
answer[node] = colour[node];
// Traversing its children
for (auto u : tree[node]) {
// Not traversing the parent
if (u == parent)
continue;
dfs(u, node, tree, colour, answer);
// If the child is adding positively to
// difference, we include it in the answer
// Otherwise, we leave the sub-tree and
// include 0 (nothing) in the answer
answer[node] += max(answer[u], 0);
}
}
int maxDiff(vector tree[], int colour[], int N)
{
int answer[N + 1];
memset(answer, 0, sizeof(answer));
// DFS for colour difference : 1colour - 2colour
dfs(1, 0, tree, colour, answer);
// Minimum colour difference is maximum answer value
int high = 0;
for (int i = 1; i <= N; i++) {
high = max(high, answer[i]);
// Clearing the current value
// to check for colour2 as well
answer[i] = 0;
}
// Interchanging the colours
for (int i = 1; i <= N; i++) {
if (colour[i] == -1)
colour[i] = 1;
else
colour[i] = -1;
}
// DFS for colour difference : 2colour - 1colour
dfs(1, 0, tree, colour, answer);
// Checking if colour2 makes the minimum colour
// difference
for (int i = 1; i < N; i++)
high = max(high, answer[i]);
return high;
}
// Driver code
int main()
{
// Nodes
int N = 5;
// Adjacency list representation
vector tree[N + 1];
// Edges
tree[1].push_back(2);
tree[2].push_back(1);
tree[1].push_back(3);
tree[3].push_back(1);
tree[2].push_back(4);
tree[4].push_back(2);
tree[3].push_back(5);
tree[5].push_back(3);
// Index represent the colour of that node
// There is no Node 0, so we start from
// index 1 to N
int colour[] = { 0, 1, 1, -1, -1, 1 };
// Printing the result
cout << maxDiff(tree, colour, N);
return 0;
}
Java
// Java code to find the sub-tree
// with minimum color difference
// in a 2-coloured tree
import java.util.*;
class GFG
{
// Tree traversal to compute minimum difference
static void dfs(int node, int parent,
Vector tree[],
int colour[], int answer[])
{
// Initial min difference is
// the color of node
answer[node] = colour[node];
// Traversing its children
for (Integer u : tree[node])
{
// Not traversing the parent
if (u == parent)
continue;
dfs(u, node, tree, colour, answer);
// If the child is adding positively to
// difference, we include it in the answer
// Otherwise, we leave the sub-tree and
// include 0 (nothing) in the answer
answer[node] += Math.max(answer[u], 0);
}
}
static int maxDiff(Vector tree[],
int colour[], int N)
{
int []answer = new int[N + 1];
// DFS for colour difference : 1colour - 2colour
dfs(1, 0, tree, colour, answer);
// Minimum colour difference is
// maximum answer value
int high = 0;
for (int i = 1; i <= N; i++)
{
high = Math.max(high, answer[i]);
// Clearing the current value
// to check for colour2 as well
answer[i] = 0;
}
// Interchanging the colours
for (int i = 1; i <= N; i++)
{
if (colour[i] == -1)
colour[i] = 1;
else
colour[i] = -1;
}
// DFS for colour difference : 2colour - 1colour
dfs(1, 0, tree, colour, answer);
// Checking if colour2 makes the
// minimum colour difference
for (int i = 1; i < N; i++)
high = Math.max(high, answer[i]);
return high;
}
// Driver code
public static void main(String []args)
{
// Nodes
int N = 5;
// Adjacency list representation
Vector tree[] = new Vector[N + 1];
for(int i = 0; i < N + 1; i++)
tree[i] = new Vector();
// Edges
tree[1].add(2);
tree[2].add(1);
tree[1].add(3);
tree[3].add(1);
tree[2].add(4);
tree[4].add(2);
tree[3].add(5);
tree[5].add(3);
// Index represent the colour of that node
// There is no Node 0, so we start from
// index 1 to N
int colour[] = { 0, 1, 1, -1, -1, 1 };
// Printing the result
System.out.println(maxDiff(tree, colour, N));
}
}
// This code is contributed by 29AjayKumar
C#
// C# code to find the sub-tree
// with minimum color difference
// in a 2-coloured tree
using System;
using System.Collections.Generic;
class GFG
{
// Tree traversal to compute minimum difference
static void dfs(int node, int parent,
List []tree,
int []colour, int []answer)
{
// Initial min difference is
// the color of node
answer[node] = colour[node];
// Traversing its children
foreach (int u in tree[node])
{
// Not traversing the parent
if (u == parent)
continue;
dfs(u, node, tree, colour, answer);
// If the child is Adding positively to
// difference, we include it in the answer
// Otherwise, we leave the sub-tree and
// include 0 (nothing) in the answer
answer[node] += Math.Max(answer[u], 0);
}
}
static int maxDiff(List []tree,
int []colour, int N)
{
int []answer = new int[N + 1];
// DFS for colour difference : 1colour - 2colour
dfs(1, 0, tree, colour, answer);
// Minimum colour difference is
// maximum answer value
int high = 0;
for (int i = 1; i <= N; i++)
{
high = Math.Max(high, answer[i]);
// Clearing the current value
// to check for colour2 as well
answer[i] = 0;
}
// Interchanging the colours
for (int i = 1; i <= N; i++)
{
if (colour[i] == -1)
colour[i] = 1;
else
colour[i] = -1;
}
// DFS for colour difference : 2colour - 1colour
dfs(1, 0, tree, colour, answer);
// Checking if colour2 makes the
// minimum colour difference
for (int i = 1; i < N; i++)
high = Math.Max(high, answer[i]);
return high;
}
// Driver code
public static void Main(String []args)
{
// Nodes
int N = 5;
// Adjacency list representation
List []tree = new List[N + 1];
for(int i = 0; i < N + 1; i++)
tree[i] = new List();
// Edges
tree[1].Add(2);
tree[2].Add(1);
tree[1].Add(3);
tree[3].Add(1);
tree[2].Add(4);
tree[4].Add(2);
tree[3].Add(5);
tree[5].Add(3);
// Index represent the colour of that node
// There is no Node 0, so we start from
// index 1 to N
int []colour = { 0, 1, 1, -1, -1, 1 };
// Printing the result
Console.WriteLine(maxDiff(tree, colour, N));
}
}
// This code is contributed by Rajput-Ji
Javascript
输出:
2
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。