今天看了一篇非常好的文章 http://blog.chinaunix.net/uid-25324849-id-2182922.html
讲解最小生成树的Prim和Kruskal算法, 看了之后, 感觉初步明白了算法的思想和流程
这里简单实现一下Prim算法, 留作笔记
输入: 第一行输入顶点的个数v和边的条数v, 随后v行依次输入编号为i的顶点到编号为j的顶的距离d
找出一条路径和最小的路径, 使得v个顶点之间都能连通(不需要直接相连),输出路径的长度, 如果不能找到这样的路径输出-1
package algorithm.mst;
import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class Prim {
public static void main(String[] args) {
Scanner cin = new Scanner(new BufferedInputStream(System.in));
int vertexCount = cin.nextInt();
int edge = cin.nextInt();
Map<Integer, Vertex> map = new HashMap<Integer, Vertex>();
for(int i=0; i<edge; i++) {
int current = cin.nextInt();
int adjacent = cin.nextInt();
int distance = cin.nextInt();
Vertex vertex = map.get(current);
if(vertex == null) {
vertex = new Vertex(current);
map.put(current, vertex);
}
vertex.adjacent.put(adjacent, distance);
Vertex node = map.get(adjacent);
if(node == null) {
node = new Vertex(adjacent);
map.put(adjacent, node);
}
node.adjacent.put(current, distance);
}
System.out.println(prim(map, vertexCount));
cin.close();
}
/**
*
* 算法思路
* 初始化
* 将所有点标记为未访问
* 任选一点作为开始, 并将该点标记的访问
* 1. 找出所有连接已访问的结点和未访问节点的边
* 2. 在这些边中选择路径最短的边, 并且将这条边中未访问的那个端点标记为访问
* 3. 重复循环到1, 直到1选出的边集合为空
*
* 这里只要输入的图是连通图, 那么2中选出来的边的集合构成的树就是最小生成树
*/
static int prim(Map<Integer, Vertex> vertexs, int vertexCount) {
List<Vertex> select = new ArrayList<Vertex>(vertexs.size());
int startId = vertexs.entrySet().iterator().next().getKey();
select.add(vertexs.remove(startId));
int sum = 0;
Edge edge = null;
while((edge = extraEdge(select, vertexs)) != null) {
sum += edge.distance;
}
return select.size() == vertexCount ? sum : -1;
}
private static Edge extraEdge(List<Vertex> select, Map<Integer, Vertex> remain) {
Edge edge = null;
for(Vertex s : select) {
for(Vertex v : remain.values()) {
if(s.adjacent.containsKey(v.id)) {
int d = s.adjacent.get(v.id);
if(edge == null) {
edge = new Edge(s.id, v.id, d);
} else {
if(d < edge.distance) {
edge = new Edge(s.id, v.id, d);
}
}
}
}
}
if(edge != null) {
select.add(remain.remove(edge.target));
}
return edge;
}
}
class Vertex {
int id;
Map<Integer, Integer> adjacent = new HashMap<Integer, Integer>();
Vertex(int current) {
id = current;
}
}
class Edge {
int source;
int target;
int distance;
@Override
public String toString() {
return "[" + source + ", " + target + ", " + distance + "]";
}
public Edge(int s, int t, int d) {
this.source = s;
this.target = t;
this.distance = d;
}
}