📜  2色树中具有最小色差的子树

📅  最后修改于: 2021-05-04 14:27:20             🧑  作者: Mango

给具有N个节点和N-1个边缘的树,为其节点提供2种不同的颜色。
查找具有最小色差的子树,即abs(1色节点– 2色节点)最小。

例子:

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,即总和(父代)+ =最小(0,总和(子代)),则取一个节点

为了获得最小和,我们可以互换节点的颜色,即-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


输出:

2