📜  树的所有对之间的最小边权的乘积

📅  最后修改于: 2021-10-25 05:07:59             🧑  作者: Mango

给定具有 N 个顶点和 N-1 个边的树。让我们定义一个函数F(a, b),它等于节点 a 和 b 之间路径中的最小边权重。任务是计算所有这些 F(a, b) 的乘积。这里 a&b 是无序对,a!=b。
所以,基本上,我们需要找到以下值:

\prod_{i, j}^nF(i, j)其中 0<=i

在输入中,我们将获得 N 的值,然后是 N-1 行。每行包含 3 个整数 u、v、w,表示节点 u 和 v 之间的边及其权重 w。由于乘积将非常大,将其取模 10^9+7 输出。
例子:

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

如果我们仔细观察,那么我们将看到,如果有一组节点的最小边权重为 w,并且如果我们向该集合中添加一个节点,该节点通过权重为 W 的边将节点与整个集连接起来,使得 W< w 那么在最近添加的节点到集合中存在的所有节点之间形成的路径将具有最小权重 W。
所以,在这里我们可以应用 Disjoint-Set Union 的概念来解决这个问题。
首先,按照权重递减对数据结构进行排序。最初将所有节点分配为一个集合。现在,当我们合并两组时,请执行以下操作:-

Product=(present weight)^(size of set1*size of set2).                    

我们将为树的所有边乘以这个乘积值。
下面是上述方法的实现:

C++
// C++ Implementation of above approach
#include 
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 > > 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


输出:
12

时间复杂度: O(N*logN)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程