最小生成树
2016-05-21 17:08
232 查看
n个点之间最多存在n(n-1)/2个边,但是在这么多点当中只需要n-1个边即可将n个点连接起来,称为生成树,这些的生成树中n-1个边的权值和最小的称为最小生成树。
如何生成最小生成树,基于最小生成树的MST性质,设顶点集为V,则存在其子集U和V-U,其一定含有一条权值最小的边(u,v)可以构成一个最小生成树。
普利姆算法:
设置一个辅助数组用以存放最小生成树的顶点。从一个顶点开始,先加入辅助数组,然后找到其权值最小的边,加入这个点至辅助数组中,再从辅助数组中的点开始找到其相邻的权值最小的边,依次这样下去,直至所有的点都在辅助数组中。
![](http://d.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=622eeac2233fb80e0c8469d303e10318/54fbb2fb43166d222c8df367442309f79152d24f.jpg)
如上的无向图,从顶点1开始生成一个无向图:
将1加入辅助数组,寻找其相邻边:1->2:12 1->5:5 1->4:8
权值最小为5,将5加入辅助数组,现在多了一些邻接边:5->2:15 5->4:6 5->3:10 5->6:8
将4加入辅助数组,再寻找邻接边:4->6:4,将6加入。
在寻找邻接边:6->3:9,将3加入。邻接边:3->2:20,由于到达2的最小权值为:1->2:12,所以加入2这个点,但是路径为1->2。
最后生成的最小生成树为:
1->2
1->5->4->6->3.
上述的算法可以描述为:选取一个顶点,找寻其邻接边,判断邻接边的权值大小,将最小邻接边的顶点加入到辅助数组中,将辅助数组中的所有点的邻接边都找到,判断权值大小,将不在辅助数组中的最小的边对应的顶点加入,重复这个过程,直至所有的顶点均在辅助数组中。
void minTree(Graph G, Type u)
{
point=u;
site=Findnext(point);//找寻u的邻接边
point=min(site);//所有邻接边中权值最小边对应的点;
visited[point]=1;
for(point=0;point<G.max;point++)
if(visited[point]=1)
{
site=Findnext(point);
point=min(site);//所有邻接边中权值最小边对应的点;
visited[point]=1;
count++;
}
if(count>=G.max)
break;
}
上述方法可以很容易的得到结果。
克鲁斯卡尔算法:
将所有的带权边按照权值从小到大排好,然后依次挑选边,只要所选的边不成环即可,终止条件为选了n-1条边。
因此这个算法里有两个部分
1.按权值大小排序。
2.判断是否成环。
成环判断可以通过并查集的方法。
如何生成最小生成树,基于最小生成树的MST性质,设顶点集为V,则存在其子集U和V-U,其一定含有一条权值最小的边(u,v)可以构成一个最小生成树。
普利姆算法:
设置一个辅助数组用以存放最小生成树的顶点。从一个顶点开始,先加入辅助数组,然后找到其权值最小的边,加入这个点至辅助数组中,再从辅助数组中的点开始找到其相邻的权值最小的边,依次这样下去,直至所有的点都在辅助数组中。
![](http://d.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=622eeac2233fb80e0c8469d303e10318/54fbb2fb43166d222c8df367442309f79152d24f.jpg)
如上的无向图,从顶点1开始生成一个无向图:
将1加入辅助数组,寻找其相邻边:1->2:12 1->5:5 1->4:8
权值最小为5,将5加入辅助数组,现在多了一些邻接边:5->2:15 5->4:6 5->3:10 5->6:8
将4加入辅助数组,再寻找邻接边:4->6:4,将6加入。
在寻找邻接边:6->3:9,将3加入。邻接边:3->2:20,由于到达2的最小权值为:1->2:12,所以加入2这个点,但是路径为1->2。
最后生成的最小生成树为:
1->2
1->5->4->6->3.
上述的算法可以描述为:选取一个顶点,找寻其邻接边,判断邻接边的权值大小,将最小邻接边的顶点加入到辅助数组中,将辅助数组中的所有点的邻接边都找到,判断权值大小,将不在辅助数组中的最小的边对应的顶点加入,重复这个过程,直至所有的顶点均在辅助数组中。
void minTree(Graph G, Type u)
{
point=u;
site=Findnext(point);//找寻u的邻接边
point=min(site);//所有邻接边中权值最小边对应的点;
visited[point]=1;
for(point=0;point<G.max;point++)
if(visited[point]=1)
{
site=Findnext(point);
point=min(site);//所有邻接边中权值最小边对应的点;
visited[point]=1;
count++;
}
if(count>=G.max)
break;
}
上述方法可以很容易的得到结果。
克鲁斯卡尔算法:
将所有的带权边按照权值从小到大排好,然后依次挑选边,只要所选的边不成环即可,终止条件为选了n-1条边。
因此这个算法里有两个部分
1.按权值大小排序。
2.判断是否成环。
成环判断可以通过并查集的方法。
相关文章推荐
- 1081 线段树练习 2
- 清除Eclipse和Myeclipse中的工作空间目录
- MySQL 相关
- 单一职责原则(SRP)
- s5pv210 datasheet_system_CONNECTIVITY/ STORAGE
- 利用VisuAlgo通过动画学习算法和数据结构
- (创建型模式)FACTORY——简单工厂模式
- C++与类相关的关键词和修饰符说明
- 决策树 算法
- Object Following for UAV(无人机物体跟随)
- 给Java新手的一些建议----Java知识点归纳(J2EE and Web 部分)
- iOS学习笔记之七--图片的移动
- Spring_Spring常见错误_error at ::0 can't find referenced pointcut解决办法
- 精度问题
- AFN和ASI的区别
- django框架从零开始_011_测试view
- 面向对象测试
- hdu_5690_All X(找循环节)
- hdu_5690_All X(找循环节)
- Eclipse+NDK 环境配置