算法导论学习笔记(四)图论之最小生成树
2016-08-25 14:51
260 查看
最小生成树是指在一个连通图中,有一个边集,使得这个边集覆盖所有点,且边的权值最小,则这个边集称为最小生成树。
算法的核心思想是贪心。
Kruskal算法是将边按权值排序,然后每次取最小的边,看边连接的两个点是否在生成树中,如果都在,则舍弃这条边,否则加入这条边,并将不在生成树的点加入生成树中。当所有边执行后,所产生的边集就是最小生成树。
Prim算法是将任意一个点选为根节点,然后每次选择离生成树最近的点,将其加入到生成树中,并更新与新加入的点相连的点与新生成树的最小距离。当所有点被加入到生成树中时,所选择的边集为最小生成树。
算法的核心思想是贪心。
Kruskal算法是将边按权值排序,然后每次取最小的边,看边连接的两个点是否在生成树中,如果都在,则舍弃这条边,否则加入这条边,并将不在生成树的点加入生成树中。当所有边执行后,所产生的边集就是最小生成树。
MST-KRUSKAL( G, w) A = EMPTY for each vertex v ∈ G.V MAKE-SET( v) sort the edges of G.E into nondecreasing order by weight w for each edge( u, v) ∈ G.E if FIND-SET( u) != FIND-SET( v) A = A U { ( u, v) } UNION( u, v) return A
Prim算法是将任意一个点选为根节点,然后每次选择离生成树最近的点,将其加入到生成树中,并更新与新加入的点相连的点与新生成树的最小距离。当所有点被加入到生成树中时,所选择的边集为最小生成树。
MST-PRIM( G, w, r) for each u G.V u.key = ∞ u.father = NIL r:key = 0 Q is a priority queue Q = G.V while Q != ∅ u = EXTRACT-MIN( Q) for each v ∈ G.Adj[u] if v Q and w( u, v) < v.key v.father = u v.key = w( u, v)
代码实现
Kruskal算法
struct Node { int u,v; int value; void setNode(int u,int v,int value){ this->u = u; this->v = v; this->value = value; } }p[110]; bool cmp(Node a,Node b) { if(a.value == b.value){ if(a.u == b.u) return a.v<b.v; return a.u < b.u; } return a.value < b.value; } int father[110]; int findFather(int i) { if(father[i] == i) return i; return father[i] = findFather(father[i]); } void buildFather(int a,int b) { if(findFather(a) != findFather(b) ) father[findFather(a)] = findFather(b); } int kruskal(int n,int m) { int sum = 0; for(int i=1;i<=n;i++) father[i] = i; sort(p,p+m,cmp); for(int i=0;i<m;i++){ if(findFather(p[i].u)!=findFather(p[i].v)) { sum += p[i].value; buildFather(p[i].u,p[i].v); } } return sum; }
Prim算法
const int INF = 0x3f3f3f3f; struct Node { int father; int key; }; int g[110][110]; Node p[110]; bool flag[110]; int prim(int n,int m) { for(int i=1;i<=n;i++){ flag[i] = false; p[i].father = i; p[i].key = INF; } p[1].key = 0; int sum = 0; while(true){ int u = 0; int key = INF; for(int i=1;i<=n;i++){ if(key > p[i].key && !flag[i]) { key = p[i].key; u = i; } } if( u == 0)break; flag[u] = true; sum += p[u].key; for(int i=1;i<=n;i++){ if( g[u][i]>0 && !flag[i] && p[i].key > g[u][i] ) { p[i].key = g[u][i]; p[i].father = u; } } } return sum; }
相关文章推荐
- 算法导论学习笔记(17)——最小生成树
- 算法导论学习笔记之五--同时得到最大和最小值复杂度3(n/2)
- 算法导论学习笔记-第六章-堆排序
- 遗传算法与直接搜索工具箱学习笔记 五-----使用GPS算法寻找一个函数的最小值
- 算法导论学习笔记-第二十一章-用于不相交集合的数据结构
- 算法导论第五章学习笔记
- 图论之 欧拉图学习笔记
- 图论之最小生成树(Prim普里姆算法)
- 算法导论学习笔记-2
- 算法导论第二章学习笔记
- 算法导论第二章学习笔记
- 任意次序的n个烙饼最小反转次数求解 暑期学习笔记(十)
- 算法导论学习笔记-第十二章-二叉查找树
- 算法导论学习笔记-第七章-快速排序
- 算法导论学习笔记-第9章 中位数和顺序统计学
- 算法导论学习笔记-第四章-递归式
- 算法导论学习笔记-第十七章-平摊分析
- 算法导论学习笔记-第十五章-动态规划
- 算法导论第四章学习笔记
- 算法导论学习笔记-第二十二章-图的基本算法