Skip to content
Related Articles

Related Articles

Improve Article

Product of minimum edge weight between all pairs of a Tree

  • Difficulty Level : Hard
  • Last Updated : 24 Jun, 2021

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: 
 

                         \prod_{i, j}^nF(i, j)  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 } });
}
 
// 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();
}

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
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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :