# Product of minimum edge weight between all pairs of a Tree

• Difficulty Level : Hard
• Last Updated : 05 May, 2022

Given a tree with N vertices and N-1 Edges. Let’s define a function F(a, b) which is equal to the minimum edge weight in the path between node a & b. The task is to calculate the product of all such F(a, b). Here a&b are unordered pairs and a!=b.
So, basically, we need to find the value of:

` where 0<=i<j<=n-1.`

In the input, we will be given the value of N and then N-1 lines follow. Each line contains 3 integers u, v, w denoting edge between node u and v and it’s weight w. Since the product will be very large, output it modulo 10^9+7.
Examples:

```Input :
N = 4
1 2 1
1 3 3
4 3 2
Output : 12
Given tree is:
1
(1)/  \(3)
2     3
\(2)
4
We will calculate the minimum edge weight between all the pairs:
F(1, 2) = 1         F(2, 3) = 1
F(1, 3) = 3         F(2, 4) = 1
F(1, 4) = 2         F(3, 4) = 2
Product of all F(i, j) = 1*3*2*1*1*2 = 12 mod (10^9 +7) =12

Input :
N = 5
1 2 1
1 3 3
4 3 2
1 5 4
Output :
288```

If we observe carefully then we will see that if there is a set of nodes in which minimum edge weight is w and if we add a node to this set that connects the node with the whole set by an edge of weight W such that W<w then path formed between recently added node to all nodes present in the set will have minimum weight W.
So, here we can apply Disjoint-Set Union concept to solve the problem.
First, sort the data structure according to decreasing weight. Initially assign all nodes as a single set. Now when we merge two sets then do the following:-

`      Product=(present weight)^(size of set1*size of set2).                    `

We will multiply this product value for all edges of the tree.
Below is the implementation of the above approach:

## C++

 `// C++ Implementation of above approach` `#include ` `using` `namespace` `std;` `#define mod 1000000007`   `// Function to return  (x^y) mod p` `int` `power(``int` `x, unsigned ``int` `y, ``int` `p)` `{` `    ``int` `res = 1;`   `    ``x = x % p;`   `    ``while` `(y > 0) {`   `        ``if` `(y & 1)` `            ``res = (res * x) % p;` `        ``y = y >> 1;` `        ``x = (x * x) % p;` `    ``}` `    ``return` `res;` `}`   `// Declaring size array globally` `int` `size;` `int` `freq;` `vector > > edges;`   `// Initializing DSU data structure` `void` `initialize(``int` `Arr[], ``int` `N)` `{` `    ``for` `(``int` `i = 0; i < N; i++) {` `        ``Arr[i] = i;` `        ``size[i] = 1;` `    ``}` `}`   `// Function to find the root of ith` `// node in the disjoint set` `int` `root(``int` `Arr[], ``int` `i)` `{` `    ``while` `(Arr[i] != i) {` `        ``i = Arr[i];` `    ``}` `    ``return` `i;` `}`   `// Weighted union using Path Compression` `void` `weighted_union(``int` `Arr[],` `                    ``int` `size[], ``int` `A, ``int` `B)` `{` `    ``int` `root_A = root(Arr, A);` `    ``int` `root_B = root(Arr, B);`   `    ``// size of set A is small than size of set B` `    ``if` `(size[root_A] < size[root_B]) {` `        ``Arr[root_A] = Arr[root_B];` `        ``size[root_B] += size[root_A];` `    ``}`   `    ``// size of set B is small than size of set A` `    ``else` `{` `        ``Arr[root_B] = Arr[root_A];` `        ``size[root_A] += size[root_B];` `    ``}` `}`   `// Function to add an edge in the tree` `void` `AddEdge(``int` `a, ``int` `b, ``int` `w)` `{` `    ``edges.push_back({ w, { a, b } });` `}`   `// Build the tree` `void` `MakeTree()` `{` `    ``AddEdge(1, 2, 1);` `    ``AddEdge(1, 3, 3);` `    ``AddEdge(3, 4, 2);` `}`   `// Function to return the required product` `int` `MinProduct()` `{` `    ``int` `result = 1;`   `    ``// Sorting the edges with respect to its weight` `    ``sort(edges.begin(), edges.end());`   `    ``// Start iterating in decreasing order of weight` `    ``for` `(``int` `i = edges.size() - 1; i >= 0; i--) {`   `        ``// Determine Current edge values` `        ``int` `curr_weight = edges[i].first;` `        ``int` `Node1 = edges[i].second.first;` `        ``int` `Node2 = edges[i].second.second;`   `        ``// Calculate root of each node` `        ``// and size of each set` `        ``int` `Root1 = root(freq, Node1);` `        ``int` `Set1_size = size[Root1];` `        ``int` `Root2 = root(freq, Node2);` `        ``int` `Set2_size = size[Root2];`   `        ``// Using the formula` `        ``int` `prod = Set1_size * Set2_size;` `        ``int` `Product = power(curr_weight, prod, mod);`   `        ``// Calculating final result` `        ``result = ((result % mod) * ` `                             ``(Product % mod)) % mod;`   `        ``// Weighted union using Path Compression` `        ``weighted_union(freq, size, Node1, Node2);` `    ``}` `    ``return` `result % mod;` `}`   `// Driver code` `int` `main()` `{` `    ``int` `n = 4;`   `    ``initialize(freq, n);`   `    ``MakeTree();`   `    ``cout << MinProduct();` `}`

## Java

 `// Java Implementation of above approach`   `import` `java.util.ArrayList;` `import` `java.util.Collections;`   `public` `class` `Product {`   `    ``// to store first vertex, second vertex and weight of` `    ``// the edge` `    ``static` `class` `Edge ``implements` `Comparable {` `        ``int` `first, second, weight;` `        ``Edge(``int` `x, ``int` `y, ``int` `w)` `        ``{` `            ``this``.first = x;` `            ``this``.second = y;` `            ``this``.weight = w;` `        ``}`   `        ``@Override` `public` `int` `compareTo(Edge edge)` `        ``{` `            ``return` `this``.weight - edge.weight;` `        ``}` `    ``}`   `    ``static` `int` `mod = ``1000000007``;`   `    ``// Function to return (x^y) mod p` `    ``static` `int` `power(``int` `x, ``int` `y, ``int` `p)` `    ``{` `        ``int` `res = ``1``;` `        ``x = x % p;` `        ``while` `(y > ``0``) {` `            ``if` `((y & ``1``) == ``1``)` `                ``res = (res * x) % p;` `            ``y = y >> ``1``;` `            ``x = (x * x) % p;` `        ``}` `        ``return` `res;` `    ``}`   `    ``// Declaring size array globally` `    ``static` `int` `size[] = ``new` `int``[``300005``];` `    ``static` `int` `freq[] = ``new` `int``[``300004``];` `    ``static` `ArrayList edges = ``new` `ArrayList();`   `    ``// Initializing DSU data structure` `    ``static` `void` `initialize(``int` `Arr[], ``int` `N)` `    ``{` `        ``for` `(``int` `i = ``0``; i < N; i++) {` `            ``Arr[i] = i;` `            ``size[i] = ``1``;` `        ``}` `    ``}`   `    ``// Function to find the root of ith` `    ``// node in the disjoint set` `    ``static` `int` `root(``int` `Arr[], ``int` `i)` `    ``{` `        ``while` `(Arr[i] != i) {` `            ``i = Arr[i];` `        ``}` `        ``return` `i;` `    ``}`   `    ``// Weighted union using Path Compression` `    ``static` `void` `weighted_union(``int` `Arr[], ``int` `size[], ``int` `A,` `                               ``int` `B)` `    ``{` `        ``int` `root_A = root(Arr, A);` `        ``int` `root_B = root(Arr, B);`   `        ``// size of set A is small than size of set B` `        ``if` `(size[root_A] < size[root_B]) {` `            ``Arr[root_A] = Arr[root_B];` `            ``size[root_B] += size[root_A];` `        ``}`   `        ``// size of set B is small than size of set A` `        ``else` `{` `            ``Arr[root_B] = Arr[root_A];` `            ``size[root_A] += size[root_B];` `        ``}` `    ``}`   `    ``// Function to add an edge in the tree` `    ``static` `void` `AddEdge(``int` `a, ``int` `b, ``int` `w)` `    ``{` `        ``edges.add(``new` `Edge(a, b, w));` `    ``}`   `    ``// Build the tree` `    ``static` `void` `MakeTree()` `    ``{` `        ``AddEdge(``1``, ``2``, ``1``);` `        ``AddEdge(``1``, ``3``, ``3``);` `        ``AddEdge(``3``, ``4``, ``2``);` `    ``}`   `    ``// Function to return the required product` `    ``static` `int` `MinProduct()` `    ``{` `        ``int` `result = ``1``;`   `        ``// Sorting the edges with respect to its weight` `        ``// ascending order` `        ``Collections.sort(edges);`   `        ``// Start iterating in decreasing order of weight` `        ``for` `(``int` `i = edges.size() - ``1``; i >= ``0``; i--) {`   `            ``// Determine Current edge values` `            ``int` `curr_weight = edges.get(i).weight;` `            ``int` `Node1 = edges.get(i).first;` `            ``int` `Node2 = edges.get(i).second;`   `            ``// Calculate root of each node` `            ``// and size of each set` `            ``int` `Root1 = root(freq, Node1);` `            ``int` `Set1_size = size[Root1];` `            ``int` `Root2 = root(freq, Node2);` `            ``int` `Set2_size = size[Root2];`   `            ``// Using the formula` `            ``int` `prod = Set1_size * Set2_size;` `            ``int` `Product = power(curr_weight, prod, mod);`   `            ``// Calculating final result` `            ``result` `                ``= ((result % mod) * (Product % mod)) % mod;`   `            ``// Weighted union using Path Compression` `            ``weighted_union(freq, size, Node1, Node2);` `        ``}` `        ``return` `result % mod;` `    ``}`   `    ``// Driver code` `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``int` `n = ``4``;` `        ``initialize(freq, n);` `        ``MakeTree();` `        ``System.out.println(MinProduct());` `    ``}` `}`   `// This code is contributed by jainlovely450`

## Python3

 `# Python3 implementation of the approach` `mod ``=` `1000000007`   `# Function to return (x^y) mod p` `def` `power(x: ``int``, y: ``int``, p: ``int``) ``-``> ``int``:` `    ``res ``=` `1` `    ``x ``%``=` `p` `    ``while` `y > ``0``:` `        ``if` `y & ``1``:` `            ``res ``=` `(res ``*` `x) ``%` `p` `        ``y ``=` `y ``/``/` `2` `        ``x ``=` `(x ``*` `x) ``%` `p` `    ``return` `res`   `# Declaring size array globally` `size ``=` `[``0``] ``*` `300005` `freq ``=` `[``0``] ``*` `300004` `edges ``=` `[]`   `# Initializing DSU data structure` `def` `initialize(arr: ``list``, N: ``int``):` `    ``for` `i ``in` `range``(N):` `        ``arr[i] ``=` `i` `        ``size[i] ``=` `1`   `# Function to find the root of ith` `# node in the disjoint set` `def` `root(arr: ``list``, i: ``int``) ``-``> ``int``:` `    ``while` `arr[i] !``=` `i:` `        ``i ``=` `arr[i]` `    ``return` `i`   `# Weighted union using Path Compression` `def` `weighted_union(arr: ``list``, size: ``list``, A: ``int``, B: ``int``):` `    ``root_A ``=` `root(arr, A)` `    ``root_B ``=` `root(arr, B)`   `    ``# size of set A is small than size of set B` `    ``if` `size[root_A] < size[root_B]:` `        ``arr[root_A] ``=` `arr[root_B]` `        ``size[root_B] ``+``=` `size[root_A]`   `    ``# size of set B is small than size of set A` `    ``else``:` `        ``arr[root_B] ``=` `arr[root_A]` `        ``size[root_A] ``+``=` `size[root_B]`   `# Function to add an edge in the tree` `def` `AddEdge(a: ``int``, b: ``int``, w: ``int``):` `    ``edges.append((w, (a, b)))`   `# Build the tree` `def` `makeTree():` `    ``AddEdge(``1``, ``2``, ``1``)` `    ``AddEdge(``1``, ``3``, ``3``)` `    ``AddEdge(``3``, ``4``, ``2``)`   `# Function to return the required product` `def` `minProduct() ``-``> ``int``:` `    ``result ``=` `1`   `    ``# Sorting the edges with respect to its weight` `    ``edges.sort(key ``=` `lambda` `a: a[``0``])`   `    ``# Start iterating in decreasing order of weight` `    ``for` `i ``in` `range``(``len``(edges) ``-` `1``, ``-``1``, ``-``1``):`   `        ``# Determine Current edge values` `        ``curr_weight ``=` `edges[i][``0``]` `        ``node1 ``=` `edges[i][``1``][``0``]` `        ``node2 ``=` `edges[i][``1``][``1``]`   `        ``# Calculate root of each node` `        ``# and size of each set` `        ``root1 ``=` `root(freq, node1)` `        ``set1_size ``=` `size[root1]` `        ``root2 ``=` `root(freq, node2)` `        ``set2_size ``=` `size[root2]`   `        ``# Using the formula` `        ``prod ``=` `set1_size ``*` `set2_size` `        ``product ``=` `power(curr_weight, prod, mod)`   `        ``# Calculating final result` `        ``result ``=` `((result ``%` `mod) ``*` `(product ``%` `mod)) ``%` `mod`   `        ``# Weighted union using Path Compression` `        ``weighted_union(freq, size, node1, node2)`   `    ``return` `result ``%` `mod`   `# Driver Code` `if` `__name__ ``=``=` `"__main__"``:`   `    ``# Number of nodes and edges` `    ``n ``=` `4` `    ``initialize(freq, n)` `    ``makeTree()` `    ``print``(minProduct())`   `# This code is contributed by` `# sanjeev2552`

## Javascript

 ``

Output:

`12`

Time Complexity : O(N*logN)

My Personal Notes arrow_drop_up
Recommended Articles
Page :