最小生成树(未完...)

Prime算法(过多遍历,适用于稠密图)

知识点

  1. 先介绍一下prime算法的思路
    定义一个数组dist记录各节点到树的最短距离
    先任意取一点作为最小生成树的起始点W,初始化,任意节点的dist值为该节点到起始点的距离,接着遍历所有节点,在与起始点相连的各节点中,找到节点V使其与起始点的边权重最小,将其加入树中,接着将V的节点置为0,更新与V相连的节点的dist值(因为这时候V已经在生成树里面的,所以dist值要更新)

然后这边我想到了一个问题

  1. 为什么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;
}

posted on 2021-06-12 21:35  不依法度  阅读(57)  评论(0)    收藏  举报

导航