Product of minimum edge weight between all pairs of a Tree

05 May, 2022
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++
Java
Python3
Javascript
// C++ Implementation of above approach#include <bits/stdc++.h>using namespace std;#define mod 1000000007 // Function to return  (x^y) mod pint 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 globallyint size[300005];int freq[300004];vector<pair<int, pair<int, int> > > edges; // Initializing DSU data structurevoid 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 setint root(int Arr[], int i){    while (Arr[i] != i) {        i = Arr[i];    }    return i;} // Weighted union using Path Compressionvoid 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 treevoid AddEdge(int a, int b, int w){    edges.push_back({ w, { a, b } });} // Build the treevoid MakeTree(){    AddEdge(1, 2, 1);    AddEdge(1, 3, 3);    AddEdge(3, 4, 2);} // Function to return the required productint 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 codeint main(){    int n = 4;     initialize(freq, n);     MakeTree();     cout << MinProduct();}
// 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<Edge> {        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<Edge> edges = new ArrayList<Edge>();     // 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 implementation of the approachmod = 1000000007 # Function to return (x^y) mod pdef 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 globallysize = [0] * 300005freq = [0] * 300004edges = [] # Initializing DSU data structuredef 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 setdef root(arr: list, i: int) -> int:    while arr[i] != i:        i = arr[i]    return i # Weighted union using Path Compressiondef 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 treedef AddEdge(a: int, b: int, w: int):    edges.append((w, (a, b))) # Build the treedef makeTree():    AddEdge(1, 2, 1)    AddEdge(1, 3, 3)    AddEdge(3, 4, 2) # Function to return the required productdef 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 Codeif __name__ == "__main__":     # Number of nodes and edges    n = 4    initialize(freq, n)    makeTree()    print(minProduct()) # This code is contributed by# sanjeev2552
<script> // JavaScript implementation of the approachconst mod = 1000000007 // Function to return (x^y) mod pfunction power(x, y, p){    let res = 1    x %= p    while(y > 0){        if(y & 1)            res = (res * x) % p        y = Math.floor(y / 2)        x = (x * x) % p    }    return res} // Declaring size array globallylet size = new Array(300005).fill(0)let freq = new Array(300004).fill(0)let edges = [] // Initializing DSU data structurefunction initialize(arr, N){    for(let i=0;i<N;i++){        arr[i] = i        size[i] = 1    }} // Function to find the root of ith// node in the disjoint setfunction root(arr, i){    while(arr[i] != i)        i = arr[i]    return i} // Weighted union using Path Compressionfunction weighted_union(arr, size, A, B){    let root_A = root(arr, A)    let 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 treefunction AddEdge(a, b, w){    edges.push([w, [a, b]])} // Build the treefunction makeTree(){    AddEdge(1, 2, 1)    AddEdge(1, 3, 3)    AddEdge(3, 4, 2)} // Function to return the required productfunction minProduct(){    let result = 1     // Sorting the edges with respect to its weight    edges.sort((a,b)=>a[0]-b[0])     // Start iterating in decreasing order of weight    for(let i=edges.length - 1;i>=0;i--){         // Determine Current edge values        let curr_weight = edges[i][0]        let node1 = edges[i][1][0]        let node2 = edges[i][1][1]         // Calculate root of each node        // and size of each set        let root1 = root(freq, node1)        let set1_size = size[root1]        let root2 = root(freq, node2)        let set2_size = size[root2]         // Using the formula        let prod = set1_size * set2_size        let 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 // Number of nodes and edgeslet n = 4initialize(freq, n)makeTree()document.write(minProduct(),"</br>") // This code is contributed by shinjanpatra</script>
12
 
Time Complexity : O(N*logN) 
sanjeev2552
arorakashish0911
jainlovely450
shinjanpatra
union-find
Graph
Sorting
Tree
Sorting
Graph
Tree
union-find
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Find if there is a path between two vertices in a directed graph
Topological Sorting
Kruskal’s Minimum Spanning Tree Algorithm | Greedy Algo-2
Detect Cycle in a Directed Graph
Introduction to Data Structures
Merge Sort
Bubble Sort Algorithm
QuickSort
Insertion Sort
Selection Sort Algorithm