prim算法---数据结构(第二版)225页。
首先,什么事prim算法(我自己的理解)
得到一个顶点集V={},我们再定义一个顶点集V1={}用来计录已经遍历过得顶点。
1、V1={v0} v0为起始顶点
2、从无向图中在到与v0连接的最小边,假设最小边连着v1。那接就将v1收录进V1={v0,v1}。
3、之后再从无向图中找到与V1顶点集中的顶点相连的最小边,再将连着的顶点收录进V1。
直到收录完所有顶点。
题目
数据结构-最小生成树
Description
给定一个有n个点的无向图,其中有m条权值为wi的边,问该图的最小生成树的费用为多少。
Input
给定两个整数分别为n,m,分别代表完全图中有n个点,有m条权值为ai的边
后面输入有m行,每行三个值u,v,w代表从u到v有一条权值为w的边
Output
最小生成树的费用,如果无法生成最小生成树,则输出Imp
思路
用二维数组来记录顶点到顶点的距离(邻接矩阵)
再用一个一维数组来记录节点到他的父节点的距离(父节点都是我们遍历过的节点且收录了的)
当收录顶点时,将他到他的父节点的距离设置为0,表示收录
每次遍历一维数组,找到最小边,并将顶点收录。
可能解答你的疑问:
1、初始设置所有节点的父节点为0
2、当节点与他的父节点有连接(对应一维数组的值不为0)
3、收录一个顶点后,要更新父节点(可能有一些顶点到以收录的集合的距离更短)
带着疑问看代码吧
c++实现
#include<iostream>
using namespace std;
#define MAX 100
#define ERROR -1
#define INF 55556
//图的结构{顶点数,边数,邻接矩阵}
struct Graph {
int Vnum;
int Enum;
int AdjMatrix[MAX][MAX];
};
//void initeGraph(Graph& G) {
// for (int i = 0; i < G.Vnum; i++) {
// for (int j = 0; j < G.Vnum; j++) {
// G.AdjMatrix[i][j] = INF;
// }
// }
//
// int stare, end, weight;
// //cout << "输入边的信息:(v1,v2,weight)" << endl;
// for (int i = 0; i < G.Enum; i++) {
// cin >> stare >> end >> weight;
// G.AdjMatrix[stare][end] = weight;
// G.AdjMatrix[end][stare] = weight;
// }
//}
int FindMinDist(Graph G, int dist[]) {
int MinV, V;
int MinDist = INF;
for (V = 0; V < G.Vnum; V++) {
if (dist[V] != 0 && dist[V] < MinDist) {
MinDist = dist[V];
MinV = V;
}
}
if (MinDist < INF) {
return MinV;
}
else {
return ERROR;
}
}
int prim(Graph G) {
int dist[MAX]; //用来记录节点i到他的父节点的距离
int TotalWeight = 0;
int parent[MAX], V, W;
int VCount = 0;
for (V = 0; V < G.Vnum; V++) {
dist[V] = G.AdjMatrix[0][V];
parent[V] = 0;
}
dist[0] = 0;
VCount++;
parent[0] = -1;
while (true) {
V = FindMinDist(G, dist);
if (V == ERROR) {
break;
}
TotalWeight += dist[V];
dist[V] = 0;
VCount++;
for (W = 0; W < G.Vnum; W++) {
if (dist[W] != 0 && G.AdjMatrix[V][W] < INF) {
if (G.AdjMatrix[V][W] < dist[W]) {
dist[W] = G.AdjMatrix[V][W];
parent[W] = V;
}
}
}
}
if (VCount < G.Vnum) {
TotalWeight = ERROR;
}
return TotalWeight;
}
int main() {
Graph G;
int Vnum;
int Enum;
cin >> Vnum;
cin >> Enum;
G.Vnum = Vnum;
G.Enum = Enum;
//initeGraph(G);
for (int i = 0; i < G.Vnum; i++) {
for (int j = 0; j < G.Vnum; j++) {
G.AdjMatrix[i][j] = INF;
}
}
int stare, end, weight;
for (int i = 0; i < G.Enum; i++) {
cin >> stare >> end >> weight;
G.AdjMatrix[--stare][--end] = weight;
G.AdjMatrix[end][stare] = weight;
}
int result = prim(G);
if (result == ERROR) {
cout << "Imp" << endl;
}
else {
cout << result << endl;
}
system("pause");
return 0;
}
java实现----我是直接参照上面的C++写的
import java.util.Scanner;
public class MinSpanTree {
final static int INF = 55556;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int Vnum = sc.nextInt();
int Enum = sc.nextInt();
int AdjMatrix[][] = new int[Vnum][Vnum];
for (int i = 0; i < Vnum; i++) {
for (int j = 0; j < Vnum; j++) {
AdjMatrix[i][j] = INF;
}
}
for (int i = 0; i < Enum; i++) {
int stare = sc.nextInt();
int end = sc.nextInt();
int weight = sc.nextInt();
AdjMatrix[--stare][--end]=weight;
AdjMatrix[end][stare]=weight;
}
int dist[] = new int[Vnum];
int parent[] = new int[Vnum];
int TotalWeight=0,VCount=0;
int V;
for(V=0;V<Vnum;V++){
dist[V] = AdjMatrix[0][V];
parent[V]=0;
}
dist[0] = 0;
VCount++;
parent[0] = -1;
while(true){
int V1,W;
int MinDist = INF;
for(V1 = 0;V1 < Vnum;V1++){
if(dist[V1]!=0&&dist[V1]<MinDist){
MinDist = dist[V1];
V = V1;
}
}
if(MinDist==INF){
break;
}
TotalWeight += dist[V];
dist[V]=0;
VCount++;
for(W = 0; W<Vnum; W++){
if(dist[W]!=0&&AdjMatrix[V][W]<INF){
if(AdjMatrix[V][W]<dist[W]){
dist[W] = AdjMatrix[V][W];
parent[W] = V;
}
}
}
}
if(VCount<Vnum){
System.out.println("Imp");
}else{
System.out.println(TotalWeight);
}
}
}