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

• Difficulty Level : Hard
• Last Updated : 12 Jan, 2023

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[300005];``int` `freq[300004];``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

 ``

## C#

 `// C# code for the above approach``using` `System;``using` `System.Collections.Generic;` `namespace` `MinimumProductSpanningTree {` `// to store first vertex, second vertex and weight of``// the edge``class` `Edge : IComparable {``    ``public` `int` `First``    ``{``        ``get``;``        ``set``;``    ``}``    ``public` `int` `Second``    ``{``        ``get``;``        ``set``;``    ``}``    ``public` `int` `Weight``    ``{``        ``get``;``        ``set``;``    ``}` `    ``public` `Edge(``int` `x, ``int` `y, ``int` `w)``    ``{``        ``First = x;``        ``Second = y;``        ``Weight = w;``    ``}` `    ``public` `int` `CompareTo(Edge edge)``    ``{``        ``return` `Weight - edge.Weight;``    ``}``}` `class` `Program {``    ``static` `readonly` `int` `Mod = 1000000007;` `    ``// Declaring size array globally``    ``static` `readonly` `int``[] Size = ``new` `int``[300005];``    ``static` `readonly` `int``[] Freq = ``new` `int``[300004];``    ``static` `readonly` `List Edges = ``new` `List();``    ``// Function to Inialize DSU``    ``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;``    ``}` `    ``static` `void` `WeightedUnion(``int``[] arr, ``int``[] size, ``int` `a,``                              ``int` `b)``    ``{``        ``int` `rootA = Root(arr, a);``        ``int` `rootB = Root(arr, b);` `        ``if` `(size[rootA] < size[rootB]) {``            ``arr[rootA] = arr[rootB];``            ``size[rootB] += size[rootA];``        ``}``        ``else` `{``            ``arr[rootB] = arr[rootA];``            ``size[rootA] += size[rootB];``        ``}``    ``}` `    ``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``        ``Edges.Sort();``        ``// Start iterating in decreasing order of weight``        ``for` `(``int` `i = Edges.Count - 1; i >= 0; i--) {``            ``// Determine Current edge values``            ``int` `currWeight = Edges[i].Weight;``            ``int` `node1 = Edges[i].First;``            ``int` `node2 = Edges[i].Second;` `            ``// Calculate root of each node``            ``// and size of each set``            ``int` `root1 = Root(Freq, node1);``            ``int` `set1Size = Size[root1];``            ``int` `root2 = Root(Freq, node2);``            ``int` `set2Size = Size[root2];``            ``// Using the formula``            ``int` `prod = set1Size * set2Size;``            ``int` `product = Power(currWeight, prod, Mod);``            ``// Calculating final result``            ``result = (result * product) % Mod;``            ``// Weighted union using Path Compression``            ``WeightedUnion(Freq, Size, node1, node2);``        ``}` `        ``return` `result;``    ``}``    ``// 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;``    ``}``    ``// Driver code``    ``static` `void` `Main(``string``[] args)``    ``{``        ``Initialize(Freq, 300004);``        ``MakeTree();``        ``Console.WriteLine(MinProduct());``    ``}``}``}``// This code is contributed by Potta Lokesh`

Output:

`12`

Time Complexity : O(N*logN)

My Personal Notes arrow_drop_up