📌  相关文章
📜  每个节点到所有其他节点的距离之和最大

📅  最后修改于: 2021-04-24 20:49:32             🧑  作者: Mango

给定一棵具有N个节点和N-1个边(根为1)的树,并给出N-1个整数的数组。任务是为树中的边缘分配权重,以使从每个节点到所有其他节点的距离之和最大

例子:

方法:可以使用组合,树上的DFS ,DP和Greedy逻辑解决问题。由于我们需要为树中的边缘分配权重,因此将最大权重分配给在所有路径中出现最大次数的边缘将是获得最大总和的方法。为了找到一条边缘在所有可能路径中出现的次数,我们需要知道边缘两侧的节点数。令c1c2为左侧和右侧节点数的计数,则在所有路径中出现边缘的次数将为c1 * c2 。按升序对c1 * c2的所有可能值进行排序。将最大权重分配给最大c1 * c2值,并以相同的方式分配给其他权重。我们可以按照以下步骤获取边的左侧和右侧的节点数:

  • 从根开始运行dfs ,并初始化dp []数组,该数组将节点的计数存储在给定节点的子树中。
  • 对每个可能的边缘进行迭代,并找到边缘两侧的节点数。
  • 要查找两侧的节点数,请找出dp [node1]dp [node2]的较小值,其中node1和node2是边缘任一侧的节点
  • 如果一侧具有min(dp [node1],dp [node2]) ,则另一侧将具有(N – min(dp [node1],dp [node2]))

下面是上述方法的实现:

C++
// C++ program to implement the
// above approach
#include 
using namespace std;
  
// Fucntion to add an edge to the tree
void addEdge(vector >& edges,
             list* tree, int x, int y)
{
    edges.push_back({ x, y });
    tree[x].push_back(y);
    tree[y].push_back(x);
}
  
// Function to run DFS and calculate the
// height of the subtree below it
void dfs(vector >& edges, list* tree,
         int node, int parent, int dp[])
{
    // Initially initialize with 1
    dp[node] = 1;
  
    // Traverse for all nodes connected to node
    for (auto it : tree[node]) {
        // If node is not parent
        // then recall dfs
        if (it != parent) {
            dfs(edges, tree, it, node, dp);
  
            // Add the size of the
            // subtree beneath it
            dp[node] += dp[it];
        }
    }
}
  
// Function to assign weights to edges
// to maximize the final sum
int maximizeSum(int a[], vector >& edges,
                list* tree, int n)
{
  
    // Initialize it which stores the
    // height of the subtree beneath it
    int dp[n + 1] = { 0 };
  
    // Call the DFS function to
    dfs(edges, tree, 1, 0, dp);
  
    // Sort the given array
    sort(a, a + (n - 1));
  
    // Stores the number of times an
    // edge is part of a path
    vector ans;
  
    // Iterate for all edges and find the
    // number of nodes on the left and on the right
    for (auto it : edges) {
  
        // Node 1
        int x = it.first;
  
        // Node 2
        int y = it.second;
  
        // If the number of nodes below is less
        // then the other will be n - dp[node]
        if (dp[x] < dp[y]) {
            int fi = dp[x];
            int sec = n - dp[x];
            ans.push_back(fi * sec);
        }
  
        // Second condition
        else {
            int fi = dp[y];
            int sec = n - dp[y];
            ans.push_back(fi * sec);
        }
    }
  
    // Sort the number of times
    // an edges occurs in the path
    sort(ans.begin(), ans.end());
    int res = 0;
  
    // Find the summation of all those
    // paths and return
    for (int i = 0; i < n - 1; i++) {
        res += ans[i] * a[i];
    }
  
    return res;
}
  
// Driver code
int main()
{
    int n = 5;
    vector > edges;
  
    list* tree = new list[n + 1];
  
    // Add an edge 1-2 in the tree
    addEdge(edges, tree, 1, 2);
  
    // Add an edge 2-3 in the tree
    addEdge(edges, tree, 1, 3);
  
    // Add an edge 3-4 in the tree
    addEdge(edges, tree, 3, 4);
  
    // Add an edge 3-5 in the tree
    addEdge(edges, tree, 3, 5);
  
    // Array which gives the edges weight
    // to be assigned
    int a[] = { 6, 3, 1, 9, 3 };
  
    cout << maximizeSum(a, edges, tree, n);
}


Python3
# Python3 program to implement the
# above approach
  
edges = [[] for i in range(100)]
tree = [[] for i in range(100)]
  
# Function to add an edge to the tree
def addEdge(x, y):
    edges.append([x, y])
    tree[x].append(y)
    tree[y].append(x)
  
# Function to run DFS and calculate the
# height of the subtree below it
def dfs(node, parent, dp):
      
    # Intially initialize with 1
    dp[node] = 1
  
    # Traverse for all nodes connected to node
    for it in tree[node]:
          
        # If node is not parent
        # then recall dfs
        if (it != parent):
            dfs(it, node, dp)
  
            # Add the size of the
            # subtree beneath it
            dp[node] += dp[it]
  
# Function to assign weights to edges
# to maximize the final sum
def maximizeSum(a, n):
  
    # Initialize it which stores the
    # height of the subtree beneath it
    dp = [0 for i in range(n + 1)]
  
    # Call the DFS function to
    dfs(1, 0, dp)
  
    # Sort the given array
    a = sorted(a[:-1])
  
    # Stores the number of times an
    # edge is part of a path
    ans = []
  
    # Iterate for all edges and find the
    # number of nodes on the left and on the right
    for it in edges:
  
        if len(it) > 0:
  
            # Node 1
            x = it[0]
  
            # Node 2
            y = it[1]
  
            # If the number of nodes below is less
            # then the other will be n - dp[node]
            if (dp[x] < dp[y]):
  
                fi = dp[x]
                sec = n - dp[x]
                ans.append(fi * sec)
  
            # Second condition
            else:
                fi = dp[y]
                sec = n - dp[y]
                ans.append(fi * sec)
  
    # Sort the number of times
    # an edges occurs in the path
    ans = sorted(ans)
    res = 0
  
    # Find the summation of all those
    # paths and return
    for i in range(n - 1):
        res += ans[i] * a[i]
  
    return res
  
# Driver code
n = 5
  
# Add an edge 1-2 in the tree
addEdge(1, 2)
  
# Add an edge 2-3 in the tree
addEdge(1, 3)
  
# Add an edge 3-4 in the tree
addEdge(3, 4)
  
# Add an edge 3-5 in the tree
addEdge(3, 5)
  
# Array which gives the edges weight
# to be assigned
a = [6, 3, 1, 9, 3]
print(maximizeSum(a, n))
  
# This code is contributed by Mohit Kumar


输出:
94