是一棵
树
贪心算法
prim算法——从根结点让一棵小树长大
- 无回路
- |v|个顶点一定有|v|-1条边
是生成树(向生成树中任加一条边都一定构成回路)
- 包含全部顶点
- |v|-1条边都在图里
边的权重和最小
贪心算法
“贪心”:每一步都要最好
“好”:权重最小的边
需要约束:只能用图里有的边,只能正海用掉|v|-1条边,不能有回路
prim算法——从根结点让一棵小树长大
下面用示意图来说明该算法:
首先以v1作为根结点
然后寻找与这棵树有关系的最小的边,所以将v1与v4的边收进来:
以v1和v4为基础再向外生长,有两种选择,v2和v3,先将v2收进来:
再将v3收进来:
继续看,不能将目前最小为3的边收进来,因为会构成回路,所以将v7收进来
然后将v6收进来:
最后将v5收进来:
void Prim()
{ MST={s};
while(1){
V=未收录顶点中dist最小值;
if(这样的V不存在)
break;
将v收录进MST:dist[v]=0;
for(V的每个邻接点 w)
{
if(dist[w]!=0)
if(E[v,w]<dist[w])
{dist[W]=E[v,w];
parent[W]=V;}
}
}
if(MST中收录的顶点不到|V|个)
cout<<"生成树不存在";
}
Kruskal算法——将森林合并成树(更彻底的贪心)
每次将权重最小的边将其收进来,因此先将权重为1的边收录进来。
将每一个顶点视为一棵树,最后将其合并为一棵树,依次类推将权值为2的边收进来。直到生成n-1条边
算法实现:
void Kruskal(Graph G)
{ MST={};
while(MST中不到|v|-1条边&&E中还有边}{
从E中取一条权值最小的边E[V,W];//最小堆
将E[V,W]从E中删除;
if(E[V,W]不在MST中构成回路)//并查集
将E[V,W]加入MST;
else
无视E[V,W];
}
if(MST中不到|V|-1条边)
cout<<"生成树不存在";
}