问题描述
n个村庄间架设通信线路,每个村庄间的距离不同,如何架设最节省开销?
这个问题中,村庄可以抽象成节点,村庄之间的距离抽象成带权值的边,要求最节约的架设方案其实就是求如何使用最少的边、最小的权值和将图中所有的节点连接起来。
这就是一个最小代价生成树的问题,可以用Prim算法或kruskal算法解决。
- PS1:无向连通图的生成树是一个极小连通子图。
- PS2:生成树是图的一个子图,包括所有的顶点和最少的边(n-1条边)。
- PS3:最小代价生成树就是所有生成树中权值之和最小的那个。
算法思路
算法的目标很明确,就是要在n个节点的图中,找出n-1个节点,并且节点之间连线的权值是最小的。因此总体思路如下:
/**
* @param a:图的邻接矩阵
*/
EdgeSet spanningTree(int[][] a){
// 结果集(边的集合)
EdgeSet solution = new EdgeSet();
// 选出n-1条边
int i = 0;
while( i<n && 还有未检查的边 ){
// 选出一条边
Edge edge = Select(a);
// 判断是否有回路
if ( !hasLoop(edge) ) {
solution.add( edge );
}
}
return solution;
}
上述为最小代价生成树的总体思路,其中选边方式(贪心准则)的不同,就产生不同的最小代价生成树算法。
图的邻接表示法
边节点
一个边节点有一条边 和 一个终止节点组成。
/**
* 边节点(由一条边和一个终止节点构成)
*/
class ENode{
int id;// 终止节点的编号
int weight;// 边的权重
}
图的邻接表示
图用一个Map< String,List>表示,其中String表示节点的编号,List中存储以该节点为起点的所有边节点。
Map<