prim算法从找点开始的算法,对于一个图如下:
解释:dist[]为每个点到生成树的最小距离,最开始时候每个点到生成树的最小距离为INF(无穷大),邻接矩阵g[][]来存储图的边数据,不相邻的边距离为INF,每个点到自己的距离为0,visited[]数组来标记每个点是否被访问了
1、刚开始时,最小生成树为空,若取顶点1位源点,则把顶点1加入到生成树中去,设置visited数组visited[1] = 1,初始化每个点到树的最小距离,此时生成树为{1,}
2、进入循环,更新dist[]数组,由于dist[3] = 1,是离树最近的点所以顶点3加入到树中,visited[3] =1 ,生成树:{1,3}
对于加入树中的顶点v,找到v的邻接点,更新dist[]数组
3、重复步骤2,找到此时离树最近的点4,加入到树中,并每次更新dist数组
4、直到所有点 都被访问过了,退出循环,打印最小生成树的长度。若退出循环后还有dist[i] = INF,说明还有点到树的距离为无穷大,说明此图不为联通图,输出"此图不联通"
示例代码:
#include<iostream>
#include<windows.h>
#define MAX 101
#define INF 99999999
using namespace std;
int g[MAX][MAX];
int visited[MAX];
int dist[MAX];
void prim(int s,int n)
{
int i,j,pos,minn;
visited[s] = 1; //将源点表示为已访问
pos = s;
int ans = 0;
for(i = 1; i <= n; i++) //dist[i]表示点i到最小生成树距离,dist[i] = 0,说明已经加入到最小生成树中了
{
dist[i] = g[s][i];
}
while(1)
{
minn = INF;
int done = 0;
for(j = 1; j <= n; j++) // 从未收录的点中找到距离树最短的顶点
{
if(visited[j] == 0 && dist[j] < minn)
{
minn = dist[j];
pos = j;
done = 1;
}
}
if(!done) //所有点都访问过了 跳出循环
{
for(j = 1; j <= n; j++)
{
if(dist[j] == INF)
{
cout<<"图不联通"<<endl;
return;
}
}
cout<<ans<<endl;
break;
}
visited[pos] = 1;
ans += minn;
// 对于新收录点的每个邻接点,更新每个点到树的距离
for(j = 1; j <= n; j++)
{
if(visited[j] == 0 && g[pos][j] < dist[j])
{
dist[j] = g[pos][j];
}
}
}
}
int main()
{
int n,m,i,j;
cin>>n>>m;
for(i = 1; i <= n; i++) //将所有不同点的距离初始化为无穷大
{
dist[i] = INF;
for(j = 1; j <= n; j++)
{
if(i == j)
{
g[i][j] = 0; // 点到自己的距离为0
}else
{
g[i][j] = INF;
}
}
}
for(i = 1; i <= m; i++)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b] = g[b][a] = c;
}
prim(1,n);
system("pause");
return 0;
}