(一)Prim算法的功能:
Prim算法实现的是找出一个有权重连通图中的最小生成树,即:具有最小权重且连接到所有结点的树。(强调的是树,树是没有回路的)。
(二)算法的基本思想:
首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出与最小生成树中各结点权重最小边,并加入到最小生成树中。加入之后如果产生回路则跳过这条边,选择下一个结点。当所有结点都加入到最小生成树中之后,就找出了连通图中的最小生成树了。
(三)算法的基本步骤:
a.假定图的顶点集合为V,边集合为E.
b.初始化点集合U={u}.//u为V中的任意选定的一点
c.从u的邻接结点中选取一点v使这两点之间的权重最小,(可能存在多条边可选,任选其中一条即可)且不构成回路,然后将v加入集合U中.
d.从结点v出发,重复c步骤,直到V={}.
(四)算法有以下几个函数构成
1.初始化图
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
map[i][j] = MAXCOST;
}
}
2.构造图
1 for (k = 1; k <= m; k++)
2 {
3 cin >> i >> j >> cost;
4 map[i][j] = cost;
5 map[j][i] = cost;
6 }
(五)优先队列表示Prim算法
1 struct node {
2 int v, len;
3 node(int v = 0, int len = 0) :v(v), len(len) {}
4 bool operator < (const node &a)const { // 加入队列的元素自动按距离从小到大排序
5 return len> a.len;
6 }
7 };
8
9 vector<node> G[maxn];
10 int vis[maxn];
11 int dis[maxn];
12
13 void init() {
14 for (int i = 0; i<maxn; i++) {
15 G[i].clear();
16 dis[i] = INF;
17 vis[i] = false;
18 }
19 }
20 int Prim(int s) {
21 priority_queue<node>Q; // 定义优先队列
22 int ans = 0;
23 Q.push(node(s,0)); // 起点加入队列
24 while (!Q.empty()) {
25 node now = Q.top(); Q.pop(); // 取出距离最小的点
26 int v = now.v;
27 if (vis[v]) continue; // 同一个节点,可能会推入2次或2次以上队列,这样第一个被标记后,剩下的需要直接跳过。
28 vis[v] = true; // 标记一下
29 ans += now.len;
30 for (int i = 0; i<G[v].size(); i++) { // 开始更新
31 int v2 = G[v][i].v;
32 int len = G[v][i].len;
33 if (!vis[v2] && dis[v2] > len) {
34 dis[v2] = len;
35 Q.push(node(v2, dis[v2])); // 更新的点加入队列并排序
36 }
37 }
38 }
39 return ans;
40 }
(六)C++完整代码
1 #include<iostream>
2 using namespace std;
3
4 #define MAX 100
5 #define MAXCOST 0x7fffffff
6
7 int map[MAX][MAX];
8 //二维数组适合复杂树
9 int prim(int map[][MAX], int n)
10 {
11 int dis[MAX];
12 int i, j, min, minid, sum = 0;
13 for (i = 2; i <= n; i++)
14 {
15 dis[i] = map[1][i];//dis[i]表示从根节点到i结点的最小距离
16 }
17 for (i = 2; i <= n; i++)
18 {
19 min = MAXCOST;
20 minid = 0;
21 for (j = 2; j <= n; j++)
22 {
23 if (dis[j] < min && dis[j] != 0)
24 {
25 min = dis[j];
26 minid = j;
27 }
28 }
29 sum += min;
30 dis[minid] = 0;
31 for (j = 2; j <= n; j++)
32 {
33 if (map[minid][j] < dis[j])
34 {
35 dis[j] = map[minid][j];
36 }
37 }
38 }
39 return sum;
40 }
41
42 int main()
43 {
44 int i, j, k, m, n;
45 int cost;
46 cin >> n >> m;//n顶点的个数,m边的个数
47 //初始化图G
48 for (i = 1; i <= n; i++)
49 {
50 for (j = 1; j <= n; j++)
51 {
52 map[i][j] = MAXCOST;
53 }
54 }
55 //构建图G
56 for (k = 1; k <= m; k++)
57 {
58 cin >> i >> j >> cost;
59 map[i][j] = cost;
60 map[j][i] = cost;
61 }
62 //求解最小生成树
63 cost = prim(map, n);
64 //输出最小权值和
65 cout << "最小权值和=" << cost << endl;
66 return 0;
67 }