最小生成树prim算法
2015-04-09 14:58
134 查看
最小生成树的由来,就是要现在n个城市之间建立道路,那么联通这n个城市至少需要n-1条路径,那问题就来了,如何建造这些路径使得最终的花费最小呢。这就用到了最小生成树了,也就是说找出点之间的一些边,然后把这些边挑出来组成一棵树。
生成最小生成树的方法有很多种,但是都是基于一种MST的思想,假设一个网络中 (带权图中),V表示顶点集合,E表示边的集合,U是V的一个非空子集,如果(u,v)是一条具有最小代价的边,其中u属于U,而v数据与V-U,那么必然存在一个最小生成树,包含此条边。
用反证法证明:假设网络N中有一个最小是生成树T,那么如果把(u,v)这条边加到T中那T必然会产生回路(生成树的定义可知),这个回路必然包含(u,v)。因为T是最小生成树,那么其必然存在一条边(u',v'),当然且u与u',v与v'必然会存在一条通路,删除(u',v')则会消除环路 生成另外一个最小生成树 T',那么问题来了 T'肯定是比T的代价小的,因为(u,v)代价比(u',v')小,这样的话就和假设矛盾了,所以原来的陈述是正确的。
prim算法 其实也就是这个思想,首先它先选择一个节点作为开始节点,然后找出与它相连的边里面权值最小并把这个边和这个点加入到生成树里面,然后再找出与现在生成树的点相连的所有边中权值最小的,并把其加入到现有生成树之中,当所有点都遍历完之后就结束了,生成树也生成了。接下来看代码吧
[align=left]#include <iostream>[/align]
[align=left]#define MAX 200[/align]
[align=left]#define NUM 9[/align]
[align=left]using namespace std;[/align]
[align=left]int a[NUM ][NUM ]={{0,10, MAX, MAX, MAX,11, MAX ,MAX , MAX},[/align]
[align=left]{10,0,18, MAX, MAX, MAX,16, MAX ,12},[/align]
[align=left]{ MAX,18,0,22, MAX ,MAX , MAX, MAX,8},[/align]
[align=left]{ MAX, MAX,22,0,20, MAX ,24,16,21},[/align]
[align=left]{ MAX, MAX, MAX,20,0,26, MAX ,7,MAX },[/align]
[align=left]{11, MAX, MAX, MAX,26,0,17, MAX ,MAX },[/align]
[align=left]{ MAX,16, MAX ,24,MAX ,17,0,19, MAX},[/align]
[align=left]{ MAX, MAX, MAX,16,7, MAX ,19,0,MAX },[/align]
[align=left]{ MAX,12,8,21, MAX ,MAX , MAX, MAX,0}[/align]
[align=left]};//邻接矩阵方法定义了图(网络),其原型为[/align]
[align=left][/align]
[align=left]typedef struct tempedg[/align]
[align=left]{[/align]
[align=left] int source;[/align]
[align=left] int des;[/align]
[align=left] int weight;[/align]
[align=left]} tempedge; //定义临时 边的存放结构,source为边的七点,des为边的终点,weight为边的权重[/align]
[align=left]tempedg FindMin(tempedg * temp, int length )[/align]
[align=left]{[/align]
[align=left] tempedg tempres=temp [0];[/align]
[align=left] int min=temp [0].weight;[/align]
[align=left] for (int i=1;i< length;i++)[/align]
[align=left] {[/align]
[align=left] if (temp [i].weight<min)[/align]
[align=left] {[/align]
[align=left] min= temp [i].weight;[/align]
[align=left] tempres= temp [i];[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] return tempres;[/align]
[align=left]}//在一群候选边中找出权值最小的候选边,应返回这条边[/align]
[align=left]int FindPoint(int * p, int bobefind, int length )[/align]
[align=left]{[/align]
[align=left] int flag=0;[/align]
[align=left] for (int i=0;i< length;i++)[/align]
[align=left] {[/align]
[align=left] if (p [i]== bobefind)[/align]
[align=left] {[/align]
[align=left] flag=1;[/align]
[align=left] break ;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] return flag;[/align]
[align=left]}//查找 候选点是否已经在点集中,如果在就不要选这条边,因为这样会形成环路[/align]
[align=left]void Prim(int g[][9])[/align]
[align=left]{[/align]
[align=left] [/align]
[align=left] int points[9],pointflag=1,min,k=0,flag=-1;[/align]
[align=left] points[0]=0;[/align]
[align=left] tempedg tempmin[9];[/align]
[align=left] while (pointflag!=9) //边界条件 将所有的点都加到生成树中[/align]
[align=left] {[/align]
[align=left] for (int j=0;j<pointflag;j++)//遍历points数组[/align]
[align=left] {[/align]
[align=left] min= MAX ;[/align]
[align=left] tempmin[j].weight= MAX ;[/align]
[align=left] for (int i=0;i< NUM;i++)//找出每个节点所连的边中哪条权值最小[/align]
[align=left] { //找出每个候选点所连接的边中权值最小的,并且找和已有节点之间的边[/align]
[align=left] if (g [points[j]][i]<min&&!FindPoint(points,i,pointflag)) [/align]
[align=left] {[/align]
[align=left] min= g [points[j]][i];[/align]
[align=left] tempmin[j].weight=min;[/align]
[align=left] tempmin[j].source=points[j];[/align]
[align=left] tempmin[j].des=i;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] tempedg tempres;[/align]
[align=left] tempres=FindMin(tempmin,pointflag);//在所有候选边中找出最优的。[/align]
cout<<tempres.source<< "
"<<tempres.des<< " "<<tempres.weight<<endl;
[align=left] pointflag++;//候选点数据长度+1[/align]
[align=left] points[pointflag-1]=tempres.des;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]
[/align]
[align=left]int main()[/align]
[align=left]{[/align]
[align=left] Prim(a);[/align]
[align=left] return 0;[/align]
[align=left]}[/align]
生成最小生成树的方法有很多种,但是都是基于一种MST的思想,假设一个网络中 (带权图中),V表示顶点集合,E表示边的集合,U是V的一个非空子集,如果(u,v)是一条具有最小代价的边,其中u属于U,而v数据与V-U,那么必然存在一个最小生成树,包含此条边。
用反证法证明:假设网络N中有一个最小是生成树T,那么如果把(u,v)这条边加到T中那T必然会产生回路(生成树的定义可知),这个回路必然包含(u,v)。因为T是最小生成树,那么其必然存在一条边(u',v'),当然且u与u',v与v'必然会存在一条通路,删除(u',v')则会消除环路 生成另外一个最小生成树 T',那么问题来了 T'肯定是比T的代价小的,因为(u,v)代价比(u',v')小,这样的话就和假设矛盾了,所以原来的陈述是正确的。
prim算法 其实也就是这个思想,首先它先选择一个节点作为开始节点,然后找出与它相连的边里面权值最小并把这个边和这个点加入到生成树里面,然后再找出与现在生成树的点相连的所有边中权值最小的,并把其加入到现有生成树之中,当所有点都遍历完之后就结束了,生成树也生成了。接下来看代码吧
[align=left]#include <iostream>[/align]
[align=left]#define MAX 200[/align]
[align=left]#define NUM 9[/align]
[align=left]using namespace std;[/align]
[align=left]int a[NUM ][NUM ]={{0,10, MAX, MAX, MAX,11, MAX ,MAX , MAX},[/align]
[align=left]{10,0,18, MAX, MAX, MAX,16, MAX ,12},[/align]
[align=left]{ MAX,18,0,22, MAX ,MAX , MAX, MAX,8},[/align]
[align=left]{ MAX, MAX,22,0,20, MAX ,24,16,21},[/align]
[align=left]{ MAX, MAX, MAX,20,0,26, MAX ,7,MAX },[/align]
[align=left]{11, MAX, MAX, MAX,26,0,17, MAX ,MAX },[/align]
[align=left]{ MAX,16, MAX ,24,MAX ,17,0,19, MAX},[/align]
[align=left]{ MAX, MAX, MAX,16,7, MAX ,19,0,MAX },[/align]
[align=left]{ MAX,12,8,21, MAX ,MAX , MAX, MAX,0}[/align]
[align=left]};//邻接矩阵方法定义了图(网络),其原型为[/align]
[align=left][/align]
[align=left]typedef struct tempedg[/align]
[align=left]{[/align]
[align=left] int source;[/align]
[align=left] int des;[/align]
[align=left] int weight;[/align]
[align=left]} tempedge; //定义临时 边的存放结构,source为边的七点,des为边的终点,weight为边的权重[/align]
[align=left]tempedg FindMin(tempedg * temp, int length )[/align]
[align=left]{[/align]
[align=left] tempedg tempres=temp [0];[/align]
[align=left] int min=temp [0].weight;[/align]
[align=left] for (int i=1;i< length;i++)[/align]
[align=left] {[/align]
[align=left] if (temp [i].weight<min)[/align]
[align=left] {[/align]
[align=left] min= temp [i].weight;[/align]
[align=left] tempres= temp [i];[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] return tempres;[/align]
[align=left]}//在一群候选边中找出权值最小的候选边,应返回这条边[/align]
[align=left]int FindPoint(int * p, int bobefind, int length )[/align]
[align=left]{[/align]
[align=left] int flag=0;[/align]
[align=left] for (int i=0;i< length;i++)[/align]
[align=left] {[/align]
[align=left] if (p [i]== bobefind)[/align]
[align=left] {[/align]
[align=left] flag=1;[/align]
[align=left] break ;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] return flag;[/align]
[align=left]}//查找 候选点是否已经在点集中,如果在就不要选这条边,因为这样会形成环路[/align]
[align=left]void Prim(int g[][9])[/align]
[align=left]{[/align]
[align=left] [/align]
[align=left] int points[9],pointflag=1,min,k=0,flag=-1;[/align]
[align=left] points[0]=0;[/align]
[align=left] tempedg tempmin[9];[/align]
[align=left] while (pointflag!=9) //边界条件 将所有的点都加到生成树中[/align]
[align=left] {[/align]
[align=left] for (int j=0;j<pointflag;j++)//遍历points数组[/align]
[align=left] {[/align]
[align=left] min= MAX ;[/align]
[align=left] tempmin[j].weight= MAX ;[/align]
[align=left] for (int i=0;i< NUM;i++)//找出每个节点所连的边中哪条权值最小[/align]
[align=left] { //找出每个候选点所连接的边中权值最小的,并且找和已有节点之间的边[/align]
[align=left] if (g [points[j]][i]<min&&!FindPoint(points,i,pointflag)) [/align]
[align=left] {[/align]
[align=left] min= g [points[j]][i];[/align]
[align=left] tempmin[j].weight=min;[/align]
[align=left] tempmin[j].source=points[j];[/align]
[align=left] tempmin[j].des=i;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] tempedg tempres;[/align]
[align=left] tempres=FindMin(tempmin,pointflag);//在所有候选边中找出最优的。[/align]
cout<<tempres.source<< "
"<<tempres.des<< " "<<tempres.weight<<endl;
[align=left] pointflag++;//候选点数据长度+1[/align]
[align=left] points[pointflag-1]=tempres.des;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]
[/align]
[align=left]int main()[/align]
[align=left]{[/align]
[align=left] Prim(a);[/align]
[align=left] return 0;[/align]
[align=left]}[/align]
相关文章推荐
- hdu 1162 Eddy's picture(最小生成树Prim算法)
- hdu 题目 (最小生成树 prim算法)
- Prim算法求解最小生成树
- POJ 1789 Truck History (Prim算法求最小生成树)
- 图基本算法 最小生成树 Prim算法(邻接表/邻接矩阵+优先队列STL)
- Prim算法的实现及应用( 最小生成树)
- 最小生成树(prim算法)
- 最小生成树prim算法
- 最小生成树prim算法实现
- 最小生成树的prim算法贪心正确性的证明
- 最小生成树prim算法实现
- 十二、图的算法入门--(2)最小生成树---Prim算法实现
- HDU-1233 还是畅通工程(最小生成树 prim算法)
- 最小生成树Prim算法实现(采用邻接表存储)C++实现
- poj-1258 Agri-Net(最小生成树 Prim算法)
- 数据结构——邻接矩阵的最小生成Prim算法
- The Unique MST POJ - 1679 判断最小生成树是否唯一 prim算法
- 最小生成树(prim算法)
- 最小生成树prim算法实现及1233解题思路
- 最小生成树——Prim算法