给定一棵具有N个节点和数字K的树。以K种可用颜色之一绘制树的每个节点。
计算并返回绘制树的方式的数量,以使距离1或2处的任何两个节点都以不同的颜色绘制。
示例:输入的第一行包含两个整数N和K。
下一行包含成对的数组。每对(x,y)表示x和y之间的无向边。
Input : N = 3 K = 3
Tree = { (2, 1), (3, 2) }
Output : 6
We have three color, say red, blue and green. we can paint in the following ways.
Node 1 | Node 2 | Node 3 |
---|---|---|
Red | Blue | Green |
Red | Green | Blue |
Blue | Red | Green |
Blue | Green | Red |
Green | Red | Blue |
Green | Blue | Red |
Thus 6 is the answer.
Input : N = 5 K = 6
Tree= { (1, 2), (5, 1), (3, 1), (4, 2) }
Output :48
方法 :
让我们在节点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)