(1)问题描述:输入:一个边加权无向连通图G=(V,E);输出:最小代价生成树。
最小生成树:1.连接图中所有的顶点2.代价最小(所有边权重之和)的生成树。(2)引入概念:
1.图割:
无向图G =(V,E)的一个割(S,V-S),是集合V的一个划分。
a.如果E中一条边(u,v)的一个端点在S中,另一个端点在V-S中,则称这条边为横跨割(S,V-S)
b.如果集合A中不存在横跨割的边,则称该集合为割尊重。
c.在横跨该割的所有边中,权重最小的边称为轻量级边(该边不唯一)。
(3)算法思想:
加点法:
每次迭代选择轻量级边对应的点,假如到最小生成树中。算法从某一个顶点开始,逐渐长大直到覆盖整个连通图的所有顶点。(贪心思想)
示意图:
(3)c++代码实现
//Graph是无向图,r是生成树的起始点
void prim(vector<vector<int>> &Graph,int r)
{
int size = Graph.size();
vector<int> visited(size);//设置访问标志变量
visited[r]=1;//将起点设置为已访问
vector<int> lowcost(size);
for(int i = 0;i<size;i++)
{
lowcost[i] = INF;
}
cout << "0";
int weight = 0;
for (int i = 0; i < size; i++)
{
int min = 99999;
int k = 1;
for (int j = 0; j < size; j++)//找出当前割的轻量级边
{
if (lowcost[j] < min&&!visited[j])
{
min = lowcost[j];
k = j;
}
}
if (k == 1 && min == 99999)
{
cout << "\n最小生成树权值为:" << weight<<endl;
return;
}
else
{
weight += min;
}
cout << " -> " << k;
visited[k] = 1;
for (int j = 1; j <size; j++)//轻量级边权值的更新
{
if ((VGraph[k][j]<lowcost[j]) && (!visited[j]))
lowcost[j] = Graph[k][j];
}
}
}
}