📌  相关文章
📜  访问无向加权树的所有节点的最小距离

📅  最后修改于: 2021-04-21 20:47:57             🧑  作者: Mango

给定一个加权树,其中N个节点从1到N开始。任何两个节点之间的距离由边缘权重给出。节点1是源,任务是以最小的传播距离访问树的所有节点。

例子:

方法:假设有n个叶子l 1l 2l 3 ,……, l n ,从根到每片叶子的路径成本为c 1c 2c 3 ,……, c n
为了从l 1l 2传播,一些边缘将被访问两次(直到l 1l 2的LCA,所有边缘将被访问两次),对于l 2l 3 ,一些边缘将被访问(直到l 2l 3的LCA为止,所有边缘将被两次访问两次,同样,树的每个边缘将被访问两次(观察)。

为了最大程度地减少旅行成本,应避免从根部到某个叶子的最大花费路径。
因此,成本=( c 1 + c 2 + c 3 +……+ c n )– max ( c 1c 2c 3 ,……, c n )
最小成本= (2 *边缘权重之和)最大( c 1c 2c 3 ,……, c n )
DFS可以进行一些修改以找到最大距离。

下面是上述方法的实现:

C++
// C++ implementation of above approach
#include 
using namespace std;
 
class Edge{
     
    public:
     
    // from - The source of an edge
    // to - destination of an edge
    // wt - distance between two nodes
    int from;
    int to;
    long wt;
 
    Edge(int a, int b, long w)
    {
        from = a;
        to = b;
        wt = w;
    }
};
 
// Method to add an edge between two nodes
void add_edge(vector> &adj_lis,
              int to, int from, long wt)
{
    adj_lis[from].push_back(Edge(from, to, wt));
    adj_lis[to].push_back(Edge(to, from, wt));
}
 
// DFS method to find distance
// between node 1 to other nodes
void dfs(vector> &adj_lis,
         long val[], int v, int par,
         long sum, bool visited[])
{
    val[v] = sum;
    visited[v] = true;
     
    for(Edge e : adj_lis[v])
    {
        if (!visited[e.to])
            dfs(adj_lis, val, e.to,
                v, sum + e.wt, visited);
    }
}
 
// Driver code
int main()
{
     
    // Number of nodes
    // V - Total number of
    // nodes in a tree
    int v = 6;
     
    // adj_lis - It is used to
    // make the adjacency list of a tree
    vector> adj_lis(v);
     
    // val - This array stores the
    // distance from node 1 to node 'n'
    long val[v];
     
    bool visited[v];
     
    int sum = 0;
     
    // Edge from a node to another
    // node with some weight
    int from[] = { 2, 3, 5, 6, 4 };
    int to[] = { 1, 1, 2, 2, 1 };
    int wt[] = { 1, 4, 2, 50, 5 };
     
    for(int i = 0; i < v - 1; i++)
    {
        sum += 2 * wt[i];
        add_edge(adj_lis, to[i] - 1,
                 from[i] - 1, wt[i]);
    }
     
    dfs(adj_lis, val, 0, -1, 0, visited);
    long large = INT_MIN;
     
    // Loop to find largest
    // distance in a val.
    int size = sizeof(val) / sizeof(long);
     
    for(int i = 1; i < size; i++)
        if (val[i] > large)
            large = val[i];
     
    cout << (sum - large);
}
 
// This code is contributed by sanjeev2552


Java
// Java implementation of the approach
import java.util.LinkedList;
import java.util.Scanner;
 
class Graph {
 
    class Edge {
 
        // from - The source of an edge
        // to - destination of an edge
        // wt - distance between two nodes
        int from;
        int to;
        long wt;
        Edge(int a, int b, long w)
        {
            from = a;
            to = b;
            wt = w;
        }
    }
 
    // adj_lis - It is used to
    // make the adjacency list of a tree
 
    // V - Total number of nodes in a tree
 
    // val - This array stores the
    // distance from node 1 to node 'n'
    static LinkedList[] adj_lis;
    static int V;
    static long val[];
 
    Graph(int v)
    {
        this.V = v;
        adj_lis = new LinkedList[V];
        for (int i = 0; i < V; i++)
            adj_lis[i] = new LinkedList<>();
    }
 
    // Method to add an edge between two nodes
    void add_edge(int to, int from, long wt)
    {
        adj_lis[from].add(
            new Edge(from, to, wt));
        adj_lis[to].add(
            new Edge(to, from, wt));
    }
 
    // DFS method to find distance
    // between node 1 to other nodes
    void dfs(int v,
             int par,
             long sum,
             boolean[] visited)
    {
        val[v] = sum;
        visited[v] = true;
        for (Edge e : adj_lis[v]) {
            if (!visited[e.to])
                dfs(e.to,
                    v,
                    sum + e.wt,
                    visited);
        }
    }
 
    // Driver code
    public static void main(String a[])
    {
 
        // Number of nodes
        int v = 6;
        Graph obj = new Graph(v);
        val = new long[v];
        boolean[] visited
            = new boolean[v];
 
        int sum = 0;
 
        // Edge from a node to another
        // node with some weight
        int from[] = { 2, 3, 5, 6, 4 };
        int to[] = { 1, 1, 2, 2, 1 };
        int wt[] = { 1, 4, 2, 50, 5 };
 
        for (int i = 0; i < v - 1; i++) {
            sum += 2 * wt[i];
            obj.add_edge(to[i] - 1,
                         from[i] - 1,
                         wt[i]);
        }
 
        obj.dfs(0, -1, 0, visited);
        long large = Integer.MIN_VALUE;
 
        // Loop to find largest
        // distance in a val.
        for (int i = 1; i < val.length;
             i++)
            if (val[i] > large)
                large = val[i];
 
        System.out.println(sum - large);
    }
}


C#
// C# implementation of above approach
using System;
using System.Collections.Generic;
class Graph
{
    public class Edge
    {
 
        // from - The source of an edge
        // to - destination of an edge
        // wt - distance between two nodes
        public int from;
        public int to;
        public long wt;
        public Edge(int a, int b, long w)
        {
            from = a;
            to = b;
            wt = w;
        }
    }
 
    // adj_lis - It is used to
    // make the adjacency list of a tree
 
    // V - Total number of nodes in a tree
 
    // val - This array stores the
    // distance from node 1 to node 'n'
    public static List[] adj_lis;
    public static int V;
    public static long []val;
 
    public Graph(int v)
    {
        V = v;
        adj_lis = new List[V];
        for (int i = 0; i < V; i++)
            adj_lis[i] = new List();
    }
 
    // Method to add an edge between two nodes
    void add_edge(int to, int from, long wt)
    {
        adj_lis[from].Add(
                 new Edge(from, to, wt));
        adj_lis[to].Add(
               new Edge(to, from, wt));
    }
 
    // DFS method to find distance
    // between node 1 to other nodes
    void dfs(int v,
            int par,
            long sum,
            bool[] visited)
    {
        val[v] = sum;
        visited[v] = true;
        foreach (Edge e in adj_lis[v])
        {
            if (!visited[e.to])
                dfs(e.to, v,
                    sum + e.wt, visited);
        }
    }
 
    // Driver code
    public static void Main(String []a)
    {
 
        // Number of nodes
        int v = 6;
        Graph obj = new Graph(v);
        val = new long[v];
        bool []visited = new bool[v];
 
        int sum = 0;
 
        // Edge from a node to another
        // node with some weight
        int []from = { 2, 3, 5, 6, 4 };
        int []to = { 1, 1, 2, 2, 1 };
        int []wt = { 1, 4, 2, 50, 5 };
 
        for (int i = 0; i < v - 1; i++)
        {
            sum += 2 * wt[i];
            obj.add_edge(to[i] - 1,
                       from[i] - 1, wt[i]);
        }
 
        obj.dfs(0, -1, 0, visited);
        long large = int.MinValue;
 
        // Loop to find largest
        // distance in a val.
        for (int i = 1; i < val.Length;
            i++)
            if (val[i] > large)
                large = val[i];
 
        Console.WriteLine(sum - large);
    }
}
 
// This code is contributed by Princi Singh


输出:
73