Prim算法
普里姆算法在找最小生成树时,将顶点分为两类,一类是在查找的过程中已经包含在树中的(假设为 A 类),剩下的是另一类(假设为 B 类)。
对于给定的连通网,起始状态全部顶点都归为 B 类。在找最小生成树时,选定任意一个顶点作为起始点,并将之从 B 类移至 A 类;然后找出 B 类中到 A 类中的顶点之间权值最小的顶点,将之从 B 类移至 A 类,如此重复,直到 B 类中没有顶点为止。所走过的顶点和边就是该连通图的最小生成树。
注意:在题目中 会存在自环和重边现象
代码:
#include <iostream>
#include <limits.h>
using namespace std;
const int inf = INT_MAX;
const int maxn = 5005;
int lowcost[maxn];
int closest[maxn]; //记录每个节点的相邻边
int mat[maxn][maxn]; //邻接矩阵
int n, m;//n个顶点
void Prim(int node) //从node节点开始prim算法搜索
{
long long res = 0; //记录权值和 作为返回值或者直接输出
for(int i=1;i<=n;++i) //初始化lowcost[]和closest[]数组
{
lowcost[i] = mat[node][i];
closest[i] = node;
}
int minE = inf;
int minF = node;
for(int x=1;x<=n-1;++x)
{
minE = inf;
for(int i=1;i<=n;++i) //找当前除了加入树内的最小边
{
if(lowcost[i] && lowcost[i] < minE)
{
minE = lowcost[i]; //minE 为最小权
minF = i; //minF 为最小边所连接的节点
}
}
res += minE; //加入总权值
lowcost[minF] = 0; //minF被访问了 将minF加入到树中
//调整
for(int i=1;i<=n;++i)
{
//如果minF距离i更近,那就记录minF,距离i最近的就是minF(目前)
if(minF != i && mat[minF][i] < lowcost[i])
{
lowcost[i] = mat[minF][i];
closest[i] =minF;
}
}
}
for(int i=1;i<=n;i++) //如果还有节点没有在在生成树内 则该图不连通
{
if(lowcost[i])
{
cout<<"-1"<<endl;
return;
}
}
cout<<res<<endl; //输出总权值
}
void getRoad(int source,int node) //获取路径
{
int pre = closest[node];
int cur = node;
stack<string> st;
while(pre != source)
{
st.push(to_string(pre)+"-("+to_string(mat[pre][cur])+")->"+to_string(cur));
cur = pre;
pre = closest[cur];
}
st.push(to_string(pre)+"-("+to_string(mat[pre][cur])+")->"+to_string(cur));
while(!st.empty())
{
cout<<st.top()<<" ";
st.pop();
}
cout<<endl;
}
void init() //初始化邻接矩阵
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
if (i == j) mat[i][j] = 0; //如果i==j 权值为0
else mat[i][j] = inf; //否则 权值为+∞
}
}
int main()
{
std::ios::sync_with_stdio(false); //关闭同步
cin >> n >> m;
init(); //初始化邻接矩阵
int a, b, c;
for (int i = 0; i < m; i++)
{
cin >> a >> b >> c;
if(mat[a][b] != inf) //找到重边中的最小边
c = min(c,mat[a][b]);
mat[a][b] = c;
mat[b][a] = c;
}
Prim(1); //从1开始prim算法开始
for(int x=2;x<=n;x++)
{
cout<<"从1到"<<x<<"的路径:";
getRoad(1,x);
}
return 0;
}