# 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

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

 // 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 {        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 edges = new ArrayList();     // 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

 # 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

## Javascript



## C#

 // C# code for the above approachusing System;using System.Collections.Generic; namespace MinimumProductSpanningTree { // to store first vertex, second vertex and weight of// the edgeclass Edge : IComparable {    public int First    {        get;        set;    }    public int Second    {        get;        set;    }    public int Weight    {        get;        set;    }     public Edge(int x, int y, int w)    {        First = x;        Second = y;        Weight = w;    }     public int CompareTo(Edge edge)    {        return Weight - edge.Weight;    }} class Program {    static readonly int Mod = 1000000007;     // Declaring size array globally    static readonly int[] Size = new int[300005];    static readonly int[] Freq = new int[300004];    static readonly List Edges = new List();    // Function to Inialize DSU    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;    }     static void WeightedUnion(int[] arr, int[] size, int a,                              int b)    {        int rootA = Root(arr, a);        int rootB = Root(arr, b);         if (size[rootA] < size[rootB]) {            arr[rootA] = arr[rootB];            size[rootB] += size[rootA];        }        else {            arr[rootB] = arr[rootA];            size[rootA] += size[rootB];        }    }     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        Edges.Sort();        // Start iterating in decreasing order of weight        for (int i = Edges.Count - 1; i >= 0; i--) {            // Determine Current edge values            int currWeight = Edges[i].Weight;            int node1 = Edges[i].First;            int node2 = Edges[i].Second;             // Calculate root of each node            // and size of each set            int root1 = Root(Freq, node1);            int set1Size = Size[root1];            int root2 = Root(Freq, node2);            int set2Size = Size[root2];            // Using the formula            int prod = set1Size * set2Size;            int product = Power(currWeight, prod, Mod);            // Calculating final result            result = (result * product) % Mod;            // Weighted union using Path Compression            WeightedUnion(Freq, Size, node1, node2);        }         return result;    }    // 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;    }    // Driver code    static void Main(string[] args)    {        Initialize(Freq, 300004);        MakeTree();        Console.WriteLine(MinProduct());    }}}// This code is contributed by Potta Lokesh

Output:
12

Time Complexity : O(N*logN)

Previous
Next