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 2Output :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) =12Input :N = 5 1 2 1 1 3 3 4 3 2 1 5 4Output :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 <bits/stdc++.h>` `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<pair<` `int` `, pair<` `int` `, ` `int` `> > > 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)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the **DSA Self Paced Course** at a student-friendly price and become industry ready.