最小生成树
定义:给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小。
方法:Kruskal算法;Prim算法;Sollin算法
一、Prim算法
其核心思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最小,此时将c点加入集合V,此时的集合V={a,b,c}直至所有顶点全部被加入V,此时就构建出了一颗最小代价生成树。因为有N个顶点,所以最小生成树就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条最小生成树的边。
例如这样一个图:
该图最小生成树为下图
顶点顺序依次为:V1-V3-V6-V4-V2-V5
权值之和=1+4+2+5+3=15
代码:
#define MAXCOST 65535
int graph[MAX][MAX];gaAX], int n)
{
int lowcost[MAX];
int mst[MAX];
int i, j, min, minid, sum = 0;
for (i = 1; i <= n; i++) //初始化
{
lowcost[i] = graph[1][i];
mst[i] = 1;
}
mst[1] = 0;
for (i = 1; i <= n; i++)
{
min = MAXCOST;
minid = 0;
for (j = 1; j <= n; j++) //找出一行中最小的权值并记录其顶点的id号
{
if (lowcost[j] < min && lowcost[j] != 0)
{
min = lowcost[j];
minid = j;
}
}
cout << "V" << mst[minid] << "-V" << minid << "=" << min << endl;
sum += min;
lowcost[minid] = 0; //将以访问过的节点权值记为0
// 对lowcost[]的值进行更新将它
for (j = 1; j <= n; j++)
{
if (graph[minid][j] < lowcost[j] && lowcost[j] !=0)
{
lowcost[j] = graph[minid][j];
mst[j] = minid;
}
}
}
return sum;
}