给定一个加权树,其中N个节点从1到N开始。任何两个节点之间的距离由边缘权重给出。节点1是源,任务是以最小的传播距离访问树的所有节点。
例子:
Input:
u[] = {1, 1, 2, 2, 1}
v[] = {2, 3, 5, 6, 4}
w[] = {1, 4, 2, 50, 5}
Output: 73
Input:
u[] = {1, 2}
v[] = {2, 3}
w[] = {3, 1}
Output: 4
方法:假设有n个叶子l 1 , l 2 , l 3 ,……, l n ,从根到每片叶子的路径成本为c 1 , c 2 , c 3 ,……, c n 。
为了从l 1到l 2传播,一些边缘将被访问两次(直到l 1和l 2的LCA,所有边缘将被访问两次),对于l 2到l 3 ,一些边缘将被访问(直到l 2和l 3的LCA为止,所有边缘将被两次访问两次,同样,树的每个边缘将被访问两次(观察)。
为了最大程度地减少旅行成本,应避免从根部到某个叶子的最大花费路径。
因此,成本=( c 1 + c 2 + c 3 +……+ c n )– max ( c 1 , c 2 , c 3 ,……, c n )
最小成本= (2 *边缘权重之和) –最大( c 1 , c 2 , c 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