最小生成树(未完...)
Prime算法(过多遍历,适用于稠密图)
知识点
- 先介绍一下prime算法的思路
定义一个数组dist记录各节点到树的最短距离
先任意取一点作为最小生成树的起始点W,初始化,任意节点的dist值为该节点到起始点的距离,接着遍历所有节点,在与起始点相连的各节点中,找到节点V使其与起始点的边权重最小,将其加入树中,接着将V的节点置为0,更新与V相连的节点的dist值(因为这时候V已经在生成树里面的,所以dist值要更新)
然后这边我想到了一个问题
- 为什么prime算法不用考虑出现环的情况?
这么说,对于图里面的任意一个节点,当其到连通图的路径不止一条,取权值最短的一条边相连的节点将其加入生成树,因为新节点标记已经访问过了,生成树里面的所有节点都标记过了,都不可能满足if的判断条件,所以不存在一条边连接最小生成树里面两个节点的情况(我觉得这句是最主要的!!)

与树有连接的最小边是v2-v4,权重为3,但这两个节点都标记过了,不可能连这条边
例题

prime的主要实现代码
void Prime(int beg, int n)
{
dist[beg] = 0;//起始点
for (int i = 1; i <= n; i++)
{
if (path[beg][i] != MAXN) {
dist[i] = path[beg][i];//与源点相邻的先跟新到树的最短距离
}
}
int count = 0;
int sum = 0;
while (count != n - 1)
{
int sign = 1;
int minp = FindMinDist(n);//找到边权重最小的相邻节点
if (minp == -1) break;//找不到权值最小边,要么节点访问完了,要么剩下最小吧都是MAXN,这个图不连通
count++;
sum += dist[minp];
dist[minp] = 0;//跟新该节点到树的最短距离
for (int i = 1; i <= n; i++)//跟新该节点相邻节点到树的最短距离
{
if (dist[i] && path[minp][i] < dist[i]) {
dist[i] = path[minp][i];
}
}
}
if (count != n - 1) cout << -1;//没有全部连通
else cout << sum;
}
例题完整代码
#include<iostream>
#include<algorithm>
#define MAXN 1000000
using namespace std;
int dist[1500];
//记录该节点到最小生成树所在的图的最短距离
//为啥没有一个数组用来标记呢,因为当访问过以后,dist[i]=0;
int path[1500][1500];
void Inti(int n);
void BuildGraph(int m);
void Prime(int beg, int n);
int FindMinDist(int n);
int sum = 0, count = 0;
int main()
{
int N, M;
cin >> N >> M;
Inti(N);
BuildGraph(M);
Prime(1, N);
return 0;
}
void Prime(int beg, int n)
{
dist[beg] = 0;//起始点
for (int i = 1; i <= n; i++)
{
if (path[beg][i] != MAXN) {
dist[i] = path[beg][i];//与源点相邻的先跟新到树的最短距离
}
}
int count = 0;
int sum = 0;
while (count != n - 1)
{
int sign = 1;
int minp = FindMinDist(n);//找到边权重最小的相邻节点
if (minp == -1) break;//找不到权值最小边,要么节点访问完了,要么剩下最小吧都是MAXN,这个图不连通
count++;
sum += dist[minp];
dist[minp] = 0;//跟新该节点到树的最短距离
for (int i = 1; i <= n; i++)//跟新该节点相邻节点到树的最短距离
{
if (dist[i] && path[minp][i] < dist[i]) {
dist[i] = path[minp][i];
}
}
}
if (count != n - 1) cout << -1;//没有全部连通
else cout << sum;
}
int FindMinDist(int n)
{
int min = MAXN, minp = -1;
for (int i = 1; i <= n; i++)
{
if (dist[i] && dist[i] < min)//最小且不构成环
{
min = dist[i];
minp = i;
}
}
return minp;
}
void BuildGraph(int m)
{
int x, y, w;
for (int i = 0; i < m; i++)
{
cin >> x >> y >> w;
path[x][y] = path[y][x] = w;
}
}
void Inti(int n)
{
for (int i = 1; i <= n; i++)
{
dist[i] = MAXN;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
path[i][j] = path[j][i] = MAXN;
}
浙公网安备 33010602011771号