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

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
```

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

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 } }); ` `} ` ` `  `// Bulid 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 Curret 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(); ` `} `

## 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))) ` ` `  `# Bulid 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 Curret 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 `

Output:

```12
```

Time Complexity : O(N*logN)

My Personal Notes arrow_drop_up Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.

Improved By : sanjeev2552