最低数量将信息传递给树中所有节点的迭代次数
给定一个非常大的 n 叉树。根节点有一些信息要传递给它的所有子节点,直到叶子节点,其约束条件是它一次只能将信息传递给它的一个子节点(将其视为一次迭代)。
现在在下一次迭代中,子节点只能将该信息传递给它的一个子节点,同时子节点的父节点(即根节点)可以将该信息传递给其剩余的一个子节点。以这种方式继续下去,我们必须找到将信息传递给树中所有节点所需的最小迭代次数。
下面树的最小迭代次数为 6。根 A 首先将信息传递给 B。在下一次迭代中,A 将信息传递给 E,B 将信息传递给 H,依此类推。
我们强烈建议您将浏览器最小化并先自己尝试一下。
这可以使用后订单遍历来完成。这个想法是考虑每个节点的高度和子节点。
如果子节点 i 进行 ci 次迭代以将信息传递到其子树下方,则其父节点将进行 (ci + 1) 次迭代以将信息传递到以该子节点 i 为根的子树。
如果父母有更多的孩子,它将在后续迭代中将信息传递给他们。假设父母的孩子需要 c1, c2, c3, c4, ..., cn 迭代来将信息传递到他们自己的子树中,现在父母必须在 n 次迭代中将信息一个接一个地传递给这 n 个孩子。如果父母在第 i 次迭代中选择了孩子 i,那么父母将进行 (i + ci) 次迭代以将信息传递给孩子 i 及其所有子树。
在任何迭代中,当父级传递一个子级 i+1 的信息时,如果任何子级(1 到 i)有其自己的孩子再往下。
为了在最小迭代中将信息传递给整个树,需要确保尽可能有效地利用带宽(即最大可通过节点数应在任何迭代中进一步向下传递信息)
最好的情况是在第 n 次迭代中,n 个不同的节点将信息传递给它们的子节点。
高度 = 0 的节点:(普通情况)叶节点没有子节点(不需要传递信息),因此迭代次数不会为零。
高度= 1的节点:这里节点必须将信息一一传递给所有子节点(所有子节点都是叶节点,因此不再向下传递更多信息)。由于所有子节点都是叶子节点,因此节点可以按任何顺序将信息传递给任何子节点(选择尚未收到信息的任何子节点)。每个孩子都需要一次迭代,因此没有迭代就没有孩子。因此,高度为 1 且有 n 个孩子的节点将进行 n 次迭代。
取一个用零初始化的计数器,循环遍历所有子节点并保持递增计数器。
高度 > 1 的节点:假设一个节点有 n 个子节点(1 到 n),并且所有 n 个子节点的最小迭代次数为 c1、c2、...、cn。
为了确保最大没有节点参与任何迭代中的信息传递,父级应首先将信息传递给将进行最大迭代以在后续迭代中进一步向下传递信息的子级。即在任何迭代中,父母应该选择以后进行最大迭代的孩子。可以将其视为一种贪心方法,其中父母选择第一个孩子,该孩子需要最大的迭代次数,以便可以有效地利用所有后续迭代。
如果父节点以任何其他方式进行,那么最后可能会有一些节点很早就完成,处于空闲状态,因此带宽在进一步的迭代中没有得到有效利用。
如果有两个具有最小迭代 ci 和 cj 的孩子 i 和 j,其中 ci > cj,那么如果父级选择第一个孩子 j,那么父级将信息传递给两个孩子及其子树所需的迭代次数将是:max (1 + cj , 2 + ci) = 2 + ci
如果父母第一次选择孩子 i,那么父母将信息传递给两个孩子及其子树所需的迭代次数将是:max(1 + ci, 2 + cj) = 1 + ci (所以选择 ci 比选择 cj 的结果更好)
这告诉父母应该在任何迭代中始终选择具有最大 ci 值的孩子 i。
所以这里贪婪的方法是:
对所有 ci 值进行降序排序,
假设排序后,值为 c1 > c2 > c3 > ...。 > 中国
取一个计数器 c,设置 c = 1 + c1 (对于具有最大迭代次数的孩子)
对于从 2 到 n 的所有孩子 i,c = c + 1 + ci
那么父级需要的总迭代次数是 max(n, c)
让minItr(A)成为将信息从节点 A 传递到它的所有子树所需的最小迭代。设child(A)为节点 A 的所有子节点的计数。因此递归关系为:
1. Get minItr(B) of all children (B) of a node (A)
2. Sort all minItr(B) in descending order
3. Get minItr of A based on all minItr(B)
minItr(A) = child(A)
For children B from i = 0 to child(A)
minItr(A) = max ( minItr(A), minItr(B) + i + 1)
Base cases would be:
If node is leaf, minItr = 0
If node's height is 1, minItr = children count
以下是上述思想的实现。
C++
// C++ program to find minimum number of iterations to pass
// information from root to all nodes in an n-ary tree
#include
using namespace std;
// A class to represent n-ary tree (Note that the implementation
// is similar to graph for simplicity of implementation
class NAryTree
{
int N; // No. of nodes in Tree
// Pointer to an array containing list of children
list *adj;
// A function used by getMinIter(), it basically does postorder
void getMinIterUtil(int v, int minItr[]);
public:
NAryTree(int N); // Constructor
// function to add a child w to v
void addChild(int v, int w);
// The main function to find minimum iterations
int getMinIter();
static int compare(const void * a, const void * b);
};
NAryTree::NAryTree(int N)
{
this->N = N;
adj = new list[N];
}
// To add a child w to v
void NAryTree::addChild(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
/* A recursive function to used by getMinIter(). This function
// mainly does postorder traversal and get minimum iteration of all children
// of node u, sort them in decreasing order and then get minimum iteration
// of node u
1. Get minItr(B) of all children (B) of a node (A)
2. Sort all minItr(B) in descending order
3. Get minItr of A based on all minItr(B)
minItr(A) = child(A) -->> child(A) is children count of node A
For children B from i = 0 to child(A)
minItr(A) = max ( minItr(A), minItr(B) + i + 1)
Base cases would be:
If node is leaf, minItr = 0
If node's height is 1, minItr = children count
*/
void NAryTree::getMinIterUtil(int u, int minItr[])
{
minItr[u] = adj[u].size();
int *minItrTemp = new int[minItr[u]];
int k = 0, tmp = 0;
// Recur for all the vertices adjacent to this vertex
list::iterator i;
for (i = adj[u].begin(); i!= adj[u].end(); ++i)
{
getMinIterUtil(*i, minItr);
minItrTemp[k++] = minItr[*i];
}
qsort(minItrTemp, minItr[u], sizeof (int), compare);
for (k = 0; k < adj[u].size(); k++)
{
tmp = minItrTemp[k] + k + 1;
minItr[u] = max(minItr[u], tmp);
}
delete[] minItrTemp;
}
// The function to do PostOrder traversal. It uses
// recursive getMinIterUtil()
int NAryTree::getMinIter()
{
// Set minimum iteration all the vertices as zero
int *minItr = new int[N];
int res = -1;
for (int i = 0; i < N; i++)
minItr[i] = 0;
// Start Post Order Traversal from Root
getMinIterUtil(0, minItr);
res = minItr[0];
delete[] minItr;
return res;
}
int NAryTree::compare(const void * a, const void * b)
{
return ( *(int*)b - *(int*)a );
}
// Driver function to test above functions
int main()
{
// TestCase 1
NAryTree tree1(17);
tree1.addChild(0, 1);
tree1.addChild(0, 2);
tree1.addChild(0, 3);
tree1.addChild(0, 4);
tree1.addChild(0, 5);
tree1.addChild(0, 6);
tree1.addChild(1, 7);
tree1.addChild(1, 8);
tree1.addChild(1, 9);
tree1.addChild(4, 10);
tree1.addChild(4, 11);
tree1.addChild(6, 12);
tree1.addChild(7, 13);
tree1.addChild(7, 14);
tree1.addChild(10, 15);
tree1.addChild(11, 16);
cout << "TestCase 1 - Minimum Iteration: "
<< tree1.getMinIter() << endl;
// TestCase 2
NAryTree tree2(3);
tree2.addChild(0, 1);
tree2.addChild(0, 2);
cout << "TestCase 2 - Minimum Iteration: "
<< tree2.getMinIter() << endl;
// TestCase 3
NAryTree tree3(1);
cout << "TestCase 3 - Minimum Iteration: "
<< tree3.getMinIter() << endl;
// TestCase 4
NAryTree tree4(6);
tree4.addChild(0, 1);
tree4.addChild(1, 2);
tree4.addChild(2, 3);
tree4.addChild(3, 4);
tree4.addChild(4, 5);
cout << "TestCase 4 - Minimum Iteration: "
<< tree4.getMinIter() << endl;
// TestCase 5
NAryTree tree5(6);
tree5.addChild(0, 1);
tree5.addChild(0, 2);
tree5.addChild(2, 3);
tree5.addChild(2, 4);
tree5.addChild(2, 5);
cout << "TestCase 5 - Minimum Iteration: "
<< tree5.getMinIter() << endl;
// TestCase 6
NAryTree tree6(6);
tree6.addChild(0, 1);
tree6.addChild(0, 2);
tree6.addChild(2, 3);
tree6.addChild(2, 4);
tree6.addChild(3, 5);
cout << "TestCase 6 - Minimum Iteration: "
<< tree6.getMinIter() << endl;
// TestCase 7
NAryTree tree7(14);
tree7.addChild(0, 1);
tree7.addChild(0, 2);
tree7.addChild(0, 3);
tree7.addChild(1, 4);
tree7.addChild(2, 5);
tree7.addChild(2, 6);
tree7.addChild(4, 7);
tree7.addChild(5, 8);
tree7.addChild(5, 9);
tree7.addChild(7, 10);
tree7.addChild(8, 11);
tree7.addChild(8, 12);
tree7.addChild(10, 13);
cout << "TestCase 7 - Minimum Iteration: "
<< tree7.getMinIter() << endl;
// TestCase 8
NAryTree tree8(14);
tree8.addChild(0, 1);
tree8.addChild(0, 2);
tree8.addChild(0, 3);
tree8.addChild(0, 4);
tree8.addChild(0, 5);
tree8.addChild(1, 6);
tree8.addChild(2, 7);
tree8.addChild(3, 8);
tree8.addChild(4, 9);
tree8.addChild(6, 10);
tree8.addChild(7, 11);
tree8.addChild(8, 12);
tree8.addChild(9, 13);
cout << "TestCase 8 - Minimum Iteration: "
<< tree8.getMinIter() << endl;
// TestCase 9
NAryTree tree9(25);
tree9.addChild(0, 1);
tree9.addChild(0, 2);
tree9.addChild(0, 3);
tree9.addChild(0, 4);
tree9.addChild(0, 5);
tree9.addChild(0, 6);
tree9.addChild(1, 7);
tree9.addChild(2, 8);
tree9.addChild(3, 9);
tree9.addChild(4, 10);
tree9.addChild(5, 11);
tree9.addChild(6, 12);
tree9.addChild(7, 13);
tree9.addChild(8, 14);
tree9.addChild(9, 15);
tree9.addChild(10, 16);
tree9.addChild(11, 17);
tree9.addChild(12, 18);
tree9.addChild(13, 19);
tree9.addChild(14, 20);
tree9.addChild(15, 21);
tree9.addChild(16, 22);
tree9.addChild(17, 23);
tree9.addChild(19, 24);
cout << "TestCase 9 - Minimum Iteration: "
<< tree9.getMinIter() << endl;
return 0;
}
Java
// Java program to find minimum number of
// iterations to pass information from
// root to all nodes in an n-ary tree
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
class GFG
{
// No. of nodes
private static int N;
// Adjacency list containing
// list of children
private static List> adj;
GFG(int N)
{
this.N = N;
adj = new ArrayList<>(N);
for (int i = 0; i < N; i++)
adj.add(new ArrayList<>());
}
// function to add a child w to v
void addChild(int v, int w)
{
adj.get(v).add(w);
}
// Main function to find the
// minimum iterations
private int getMinIteration()
{
// Base case : if height = 0 or 1;
if (N == 0 || N == 1)
return 0;
int[] mintItr = new int[N];
// Start Post Order Traversal from Root
getMinIterUtil(0, mintItr);
return mintItr[0];
}
/* A recursive function to used by getMinIter().
This function mainly does postorder traversal
and get minimum iteration of all children
of parent node, sort them in decreasing order
and then get minimum iteration of parent node
1. Get minItr(B) of all children (B) of a node (A)
2. Sort all minItr(B) in descending order
3. Get minItr of A based on all minItr(B)
minItr(A) = child(A) -->> child(A)
is children count of node A
For children B from i = 0 to child(A)
minItr(A) = max (minItr(A),
minItr(B) + i + 1)
Base cases would be:
If node is leaf, minItr = 0
If node's height is 1, minItr = children count
*/
private void getMinIterUtil(int u, int[] minItr)
{
// Base case : Leaf node
if (adj.get(u).size() == 0)
return;
minItr[u] = adj.get(u).size();
Integer[] minItrTemp = new Integer[minItr[u]];
int k = 0;
Iterator itr = adj.get(u).iterator();
while (itr.hasNext())
{
int currentChild = (int) itr.next();
getMinIterUtil(currentChild, minItr);
minItrTemp[k++] = minItr[currentChild];
}
Arrays.sort(minItrTemp, Collections.reverseOrder());
for (k = 0; k < adj.get(u).size(); k++)
{
int temp = minItrTemp[k] + k + 1;
minItr[u] = Math.max(minItr[u], temp);
}
}
// Driver Code
public static void main(String args[])
{
// TestCase1
GFG testCase1 = new GFG(17);
testCase1.addChild(0, 1);
testCase1.addChild(0, 2);
testCase1.addChild(0, 3);
testCase1.addChild(0, 4);
testCase1.addChild(0, 5);
testCase1.addChild(0, 6);
testCase1.addChild(1, 7);
testCase1.addChild(1, 8);
testCase1.addChild(1, 9);
testCase1.addChild(4, 10);
testCase1.addChild(4, 11);
testCase1.addChild(6, 12);
testCase1.addChild(7, 13);
testCase1.addChild(7, 14);
testCase1.addChild(10, 15);
testCase1.addChild(11, 16);
System.out.println("TestCase 1 - Minimum Iteration: " +
testCase1.getMinIteration());
// TestCase2
GFG testCase2 = new GFG(3);
testCase2.addChild(0, 1);
testCase2.addChild(0, 2);
System.out.println("TestCase 2 - Minimum Iteration: " +
testCase2.getMinIteration());
// TestCase3
GFG testCase3 = new GFG(1);
System.out.println("TestCase 3 - Minimum Iteration: " +
testCase3.getMinIteration());
// TestCase4
GFG testCase4 = new GFG(6);
testCase4.addChild(0, 1);
testCase4.addChild(1, 2);
testCase4.addChild(2, 3);
testCase4.addChild(3, 4);
testCase4.addChild(4, 5);
System.out.println("TestCase 4 - Minimum Iteration: " +
testCase4.getMinIteration());
// TestCase 5
GFG testCase5 = new GFG(6);
testCase5.addChild(0, 1);
testCase5.addChild(0, 2);
testCase5.addChild(2, 3);
testCase5.addChild(2, 4);
testCase5.addChild(2, 5);
System.out.println("TestCase 5 - Minimum Iteration: " +
testCase5.getMinIteration());
// TestCase 6
GFG testCase6 = new GFG(6);
testCase6.addChild(0, 1);
testCase6.addChild(0, 2);
testCase6.addChild(2, 3);
testCase6.addChild(2, 4);
testCase6.addChild(3, 5);
System.out.println("TestCase 6 - Minimum Iteration: " +
testCase6.getMinIteration());
// TestCase 7
GFG testCase7 = new GFG(14);
testCase7.addChild(0, 1);
testCase7.addChild(0, 2);
testCase7.addChild(0, 3);
testCase7.addChild(1, 4);
testCase7.addChild(2, 5);
testCase7.addChild(2, 6);
testCase7.addChild(4, 7);
testCase7.addChild(5, 8);
testCase7.addChild(5, 9);
testCase7.addChild(7, 10);
testCase7.addChild(8, 11);
testCase7.addChild(8, 12);
testCase7.addChild(10, 13);
System.out.println("TestCase 7 - Minimum Iteration: " +
testCase7.getMinIteration());
// TestCase 8
GFG testCase8 = new GFG(14);
testCase8.addChild(0, 1);
testCase8.addChild(0, 2);
testCase8.addChild(0, 3);
testCase8.addChild(0, 4);
testCase8.addChild(0, 5);
testCase8.addChild(1, 6);
testCase8.addChild(2, 7);
testCase8.addChild(3, 8);
testCase8.addChild(4, 9);
testCase8.addChild(6, 10);
testCase8.addChild(7, 11);
testCase8.addChild(8, 12);
testCase8.addChild(9, 13);
System.out.println("TestCase 8 - Minimum Iteration: " +
testCase8.getMinIteration());
// TestCase 9
GFG testCase9 = new GFG(25);
testCase9.addChild(0, 1);
testCase9.addChild(0, 2);
testCase9.addChild(0, 3);
testCase9.addChild(0, 4);
testCase9.addChild(0, 5);
testCase9.addChild(0, 6);
testCase9.addChild(1, 7);
testCase9.addChild(2, 8);
testCase9.addChild(3, 9);
testCase9.addChild(4, 10);
testCase9.addChild(5, 11);
testCase9.addChild(6, 12);
testCase9.addChild(7, 13);
testCase9.addChild(8, 14);
testCase9.addChild(9, 15);
testCase9.addChild(10, 16);
testCase9.addChild(11, 17);
testCase9.addChild(12, 18);
testCase9.addChild(13, 19);
testCase9.addChild(14, 20);
testCase9.addChild(15, 21);
testCase9.addChild(16, 22);
testCase9.addChild(17, 23);
testCase9.addChild(19, 24);
System.out.println("TestCase 9 - Minimum Iteration: " +
testCase9.getMinIteration());
}
}
// This code is contributed
// by MitaliSrivastava
C#
// C# program to find minimum number of
// iterations to pass information from
// root to all nodes in an n-ary tree
using System;
using System.Collections.Generic;
class GFG
{
// No. of nodes
public int N;
// Adjacency list containing
// list of children
static List> adj;
public GFG(int N)
{
this.N = N;
adj = new List>(N);
for (int i = 0; i < N; i++)
adj.Add(new List());
}
// function to add a child w to v
void addChild(int v, int w)
{
adj[v].Add(w);
}
// Main function to find the
// minimum iterations
private int getMinIteration()
{
// Base case : if height = 0 or 1;
if (N == 0 || N == 1)
return 0;
int[] mintItr = new int[N];
// Start Post Order Traversal from Root
getMinIterUtil(0, mintItr);
return mintItr[0];
}
/* A recursive function to used by getMinIter().
This function mainly does postorder traversal
and get minimum iteration of all children
of parent node, sort them in decreasing order
and then get minimum iteration of parent node
1. Get minItr(B) of all children (B) of a node (A)
2. Sort all minItr(B) in descending order
3. Get minItr of A based on all minItr(B)
minItr(A) = child(A) -->> child(A)
is children count of node A
For children B from i = 0 to child(A)
minItr(A) = max (minItr(A),
minItr(B) + i + 1)
Base cases would be:
If node is leaf, minItr = 0
If node's height is 1, minItr = children count
*/
private void getMinIterUtil(int u, int[] minItr)
{
// Base case : Leaf node
if (adj[u].Count == 0)
return;
minItr[u] = adj[u].Count;
int[] minItrTemp = new int[minItr[u]];
int k = 0;
// Iterator itr = adj.get(u).iterator();
foreach (int itr in adj[u])
{
int currentChild = (int) itr;
getMinIterUtil(currentChild, minItr);
minItrTemp[k++] = minItr[currentChild];
}
Array.Sort(minItrTemp);
for(int i =0, j = minItrTemp.Length-1; i
Javascript
输出:
TestCase 1 - Minimum Iteration: 6
TestCase 2 - Minimum Iteration: 2
TestCase 3 - Minimum Iteration: 0
TestCase 4 - Minimum Iteration: 5
TestCase 5 - Minimum Iteration: 4
TestCase 6 - Minimum Iteration: 3
TestCase 7 - Minimum Iteration: 6
TestCase 8 - Minimum Iteration: 6
TestCase 9 - Minimum Iteration: 8