Prim
作者:刘伟
#include<iostream>
using namespace std;
#define MAXN 2001
#define INF 1000000
int n, m;
int G[MAXN][MAXN]; //存储图
void init(){
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < n ; j++)
G[i][j] = INF; //初始化图中两点间距离为无穷大
}
}
void prim(){
int closeset[n], //记录不在S中的顶点在S中的最近邻接点
lowcost[n], //记录不在S中的顶点到S的最短距离,即到最近邻接点的权值
used[n]; //标记顶点是否被访问,访问过的顶点标记为1
for (int i = 0; i < n; i++)
{
//初始化,S中只有第1个点(0)
lowcost[i] = G[0][i]; //获取其他顶点到第1个点(0)的距离,不直接相邻的顶点距离为无穷大
closeset[i] = 0; //初始情况下所有点的最近邻接点都为第1个点(0)
used[i] = 0; //初始情况下所有点都没有被访问过
}
used[0] = 1; //访问第1个点(0),将第1个点加到S中
//每一次循环找出一个到S距离最近的顶点
for (int i = 1; i < n; i++)
{
int j = 0;
//每一次循环计算所有没有使用的顶点到当前S的距离,得到在没有使用的顶点中到S的最短距离以及顶点号
for (int k = 0; k < n; k++)
if ((!used[k]) && (lowcost[k] < lowcost[j])) j = k; //如果顶点k没有被使用,且到S的距离小于j到S的距离,将k赋给j
printf("%d %d %d\n",closeset[j] + 1, j + 1, lowcost[j]); //输出S中与j最近邻点,j,以及它们之间的距离
used[j] = 1; //将j增加到S中
//每一次循环用于在j加入S后,重新计算不在S中的顶点到S的距离
//主要是修改与j相邻的边到S的距离,修改lowcost和closeset
for (int k = 0; k < n; k++)
{
if ((!used[k]) && (G[j][k] < lowcost[k])) //松弛操作,如果k没有被使用,且k到j的距离比原来k到S的距离小
{
lowcost[k] = G[j][k]; //将k到j的距离作为新的k到S之间的距离
closeset[k] = j; //将j作为k在S中的最近邻点
}
}
}
}
int main(){
int a , b , w;
scanf("%d%d" , &n , &m);
init();
for(int i = 0 ; i < m ; i++){
scanf("%d%d%d" , &a , &b , &w);
if(G[a-1][b-1] > w)
G[a-1][b-1] = G[b-1][a-1] = w; //无向图赋权值
}
prim();
system("pause");
return 0;
}