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