📌  相关文章
📜  在给定条件下用K种不同颜色绘制N个节点的树的方法数量

📅  最后修改于: 2021-04-27 19:49:57             🧑  作者: Mango

给定一棵具有N个节点和数字K的树。以K种可用颜色之一绘制树的每个节点。
计算并返回绘制树的方式的数量,以使距离1或2处的任何两个节点都以不同的颜色绘制。

示例:输入的第一行包含两个整数N和K。
下一行包含成对的数组。每对(x,y)表示x和y之间的无向边。

方法 :
让我们在节点1处将树作为根,然后从根向下移动到叶子开始对其进行绘制。对于根,我们可以用k种可用颜色对其进行绘制。如果根有x个子代,我们可以用k-1 P x种方式对其进行绘制,即
(k-1)!/(k-1-x)!.因为每个孩子都必须使用不同的颜色,并且所有颜色都应与根使用的颜色不同。

现在,对于其余的节点,我们一次绘制特定节点v的所有子节点。它们的颜色必须与v和v的父亲使用的颜色不同且不同。因此,如果v有x个儿子,我们可以用k-2 P x种方式绘制它们

下面是上述方法的实现:

// C++ Implementation of above approach
#include 
using namespace std;
const int maxx = 1e5;
vector tree[maxx];
int degree_of_node[maxx], parent_of_node[maxx],
    child_of_node[maxx], flag = -1;
  
// Function to calculate number of children
// of every node in a tree with root 1
void dfs(int current, int parent)
{
    parent_of_node[current] = parent;
    for (int& child : tree[current]) {
  
        // If current and parent are same we have
        // already visited it, so no need to visit again
        if (child == parent)
            return;
        dfs(child, current);
    }
  
    // If the current node is a leaf node
    if (degree_of_node[current] == 1 && current != 1) {
  
        // For leaf nodes there will be no child.
        child_of_node[current] = 0;
        return;
    }
  
    // Gives the total child of current node
    int total_child = 0;
    for (auto& child : tree[current]) {
        if (child == parent)
            return;
        else
            ++total_child;
    }
    child_of_node[current] = total_child;
    return;
}
  
// Function to calculate permuations ( nPr )
int find_nPr(int N, int R)
{
    if (R > N) {
        flag = 0;
        return 0;
    }
    int total = 1;
    for (int i = N - R + 1; i <= N; ++i) {
        total = total * i;
    }
    return total;
}
  
// Function to calculate the number of ways
// to paint the tree according to given conditions
int NoOfWays(int Nodes, int colors)
{
  
    // Do dfs to find parent and child of a node,
    // we root the tree at node 1.
    dfs(1, -1);
  
    // Now start iterating for all nodes of
    // the tree and count the number of ways to
    // paint its children and node itself
    int ways = 0;
    for (int i = 1; i <= Nodes; ++i) {
  
        // If the current node is root node, then
        // we have total of K ways to paint it and
        // (k-1)P(x) to paint its child
        if (i == 1) {
            ways = ways + colors * 
                   find_nPr(colors - 1, child_of_node[1]);
        }
        else {
  
            // For other remaining nodes which are not
            // leaf nodes we have (k-2)P(x) to paint
            // its children, we will not take into
            // consideration of current node
            // since we already painted it.
            if (degree_of_node[i] == 1) {
                continue;
            }
            else {
                ways = ways * 
                find_nPr(colors - 2, child_of_node[i]);
            }
        }
    }
    return ways;
}
  
// Function to build the tree
void MakeTree()
{
  
    tree[2].push_back(1);
    tree[1].push_back(2);
    tree[3].push_back(2);
    tree[2].push_back(3);
    degree_of_node[2]++;
    degree_of_node[1]++;
    degree_of_node[3]++;
    degree_of_node[2]++;
}
  
// Driver Code
int main()
{
    int N = 3, K = 3;
    MakeTree();
    int Count = NoOfWays(N, K);
    cout << Count << "\n";
    return 0;
}
输出:
6

时间复杂度:O(N)