我们有一个加权图,我们想根据以下条件制作一棵最优树:
1) 树应该包含图中的所有顶点
2) 所有的树边都应该在图中
3) 从顶点U开始,以最小路径到达任何其他顶点。
根据初始图和条件,我们想要制作一棵具有最小权重的树。
例如:
输入
6 8
1 2 30
1 3 20
2 3 50
4 2 100
2 5 40
3 5 10
3 6 50
5 6 60
4
输出: 230
解释: 我们有 6 个顶点和 8 条边。之后我们有 8 strip 有树编号的线。例如 (2 3 50) 表示顶点 2 与顶点 3 相连,权重为 50。
最后我们有一个数字显示起始顶点。
所以如果我们从顶点 4 开始并以最小路径到达所有其他顶点,我们可以得到一棵总权重为 230 的树
最佳答案
您可以使用 Dijkstra's algorithm与 U
作为起始节点。它将为您提供从 U
到所有顶点的最短距离.如果你只考虑那些用于计算到所有顶点的最短距离的边,你将得到所需的树。
现在要获得所有边,您需要对算法进行一些修改。您需要维护一个父数组,该数组保留有关当前顶点所依赖的顶点的信息(同时计算最短距离)。
例如,我们有两个顶点U
和 V
和来自某个来源的所有顶点的距离S
存储在 distance[]
大批。
现在假设我们有一条边 E
在U
之间和 V
有重量W
和条件 distance[U] > distance[V] + W
得到满足,然后 parent
的 U
将是 V
作为distance[U]
现在取决于 distance[V]
.
因此我们将在更新 distance
的算法中再添加一步.最初 parent[source]
将是 source
本身,因为它不依赖于任何其他顶点。
最后,要获得所有边,您需要遍历 parent
排列并打印 index <-> parent[index]
.
Java 示例代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class ModifiedDijkstra {
public static final long INF = (long) 1e15;
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int totalVertices = sc.nextInt();
int totalEdges = sc.nextInt();
ArrayList<Edge> adjacencyList[] = new ArrayList[totalVertices + 1];
for (int i = 1; i <= totalVertices; i++)
adjacencyList[i] = new ArrayList<>();
for (int i = 0; i < totalEdges; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
long weight = sc.nextInt();
adjacencyList[u].add(new Edge(v, weight));
adjacencyList[v].add(new Edge(u, weight));
}
int source = sc.nextInt(); //Source Index
long distance[] = new long[totalVertices + 1];
long edgesWeights[] = new long[totalVertices + 1];
Arrays.fill(distance, INF);
int parent[] = new int[totalVertices + 1];
distance[source] = 0;
parent[source] = source;
Queue<Integer> queue = new LinkedList<>();
queue.add(source);
while (!queue.isEmpty()) {
int currVertex = queue.poll();
for (Edge edge : adjacencyList[currVertex]) {
if (distance[edge.endVertex] > distance[currVertex] + edge.weight) {
distance[edge.endVertex] = distance[currVertex] + edge.weight;
parent[edge.endVertex] = currVertex;
edgesWeights[edge.endVertex] = edge.weight;
queue.add(edge.endVertex);
}
}
}
System.out.println("TREE : ");
long edgesSum = 0;
for (int i = 1; i <= totalVertices; i++) {
if (parent[i] == i) //source
continue;
//Vertex1 <-> Vertex2 : Weight
System.out.println(i + " <-> " + parent[i] + " : " + edgesWeights[i]);
edgesSum += edgesWeights[i];
}
System.out.println("Sum of the weights of all edges is : " + edgesSum);
}
}
class Edge {
int endVertex;
long weight;
public Edge(int endVertex, long weight) {
this.endVertex = endVertex;
this.weight = weight;
}
}
输入:
6 8
1 2 30
1 3 20
2 3 50
4 2 100
2 5 40
3 5 10
3 6 50
5 6 60
4
输出:
TREE :
1 <-> 2 : 30
2 <-> 4 : 100
3 <-> 2 : 50
5 <-> 2 : 40
6 <-> 3 : 50
Sum of the weights of all edges is : 270
关于algorithm - 我怎样才能制作出满足某些条件的最佳树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49679065/