最小生成树(先写个prim,kruscal)
2017-12-14 15:40
337 查看
概念:
生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。
最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。
此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
1. 把图中的所有边按代价从小到大排序;
2. 把图中的n个顶点看成独立的n棵树组成的森林;
3. 按权值从小到大选择边,所选的边连接的两个顶点ui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。
4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。
代码:
//Kruscal.h
//Kruscal.cc
//main.cc
1图的所有顶点集合为V;初始令集合u={s},v=V−u;
2在两个集合u,v能够组成的边中,选择一条代价最小的边(u0,v0),加入到最小生成树中,并把v0并入到集合u中。
3重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。
代码:
//Prim.h
//Prim.cc
//main.cc
生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。
最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。
一、kruscal
算法流程:此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
1. 把图中的所有边按代价从小到大排序;
2. 把图中的n个顶点看成独立的n棵树组成的森林;
3. 按权值从小到大选择边,所选的边连接的两个顶点ui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。
4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。
代码:
//Kruscal.h
#ifndef __KRUSKAL_H #define __KRUSKAL_H #include <vector> using namespace std; struct edge { int source; int destination; int weight; }; typedef struct edge edge; void sortEdge(vector<edge>& vecedge); void KruskalAcc(vector<edge>& vecedge, int numOfNode); #endif
//Kruscal.cc
#include "Kruskal.h" #include <cstdlib> #include <iostream> using namespace std; int compar(const void* p1, const void* p2) { return (*(edge*)p1).weight - (*(edge*)p2).weight; } int Parent(vector<int>& parent, int i) { if (i != parent[i]) { parent[i] = Parent(parent, parent[i]); } return parent[i]; } void sortEdge(vector<edge>& vecedge) { qsort(&*vecedge.begin(), vecedge.size(), sizeof(edge), compar); } void KruskalAcc(vector<edge>& vecedge, int numOfNode) { sortEdge(vecedge); if (numOfNode < 2) { return; } vector<int> parent(numOfNode, 0); for (int i = 0; i < numOfNode; ++i) { parent[i] = i; } int senlin = numOfNode; vector<edge> res; for (int i = 0; i < vecedge.size() && senlin>1; ++i) { const edge& e = vecedge[i]; int m = Parent(parent, e.source); int n = Parent(parent, e.destination); if (m!=n) { parent = m; res.push_back(e); --senlin; } } for (int i = 0; i < res.size(); ++i) { cout << res[i].source << "----" << res[i].destination <<": "<<res[i].weight<< endl; } cout << endl; }
//main.cc
#include "Kruskal.h" #include <stdlib.h> #include <iostream> using namespace std; int main() { //testThrowCoins(); int nodeOfnumber; vector<edge> input; cin >> nodeOfnumber; edge tmp; while (cin >> tmp.source >> tmp.destination >> tmp.weight) { input.push_back(tmp); } KruskalAcc(input, nodeOfnumber); //testDijkstra(); system("pause"); return 0;
Prim
此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。1图的所有顶点集合为V;初始令集合u={s},v=V−u;
2在两个集合u,v能够组成的边中,选择一条代价最小的边(u0,v0),加入到最小生成树中,并把v0并入到集合u中。
3重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。
代码:
//Prim.h
#ifndef __PRIM_H #define __PRIM_H #include <vector> using namespace std; void Prim(vector< vector<int> >& vec, int source); #endif
//Prim.cc
#include "Prim.h" #include <assert.h> #include <stdint.h> #include <iostream> void Prim(vector< vector<int> >& vec,int source) { int siz = vec.size(); assert(siz >= 2); vector<int> visited(siz, 0); visited[source] = 1; vector<int> dist(siz, INT_MAX); vector<int> prev(siz, -1); dist[source] = 0; vector<int> res; res.push_back(source); int nodeleave = siz - 1; while (nodeleave > 0) { //1、更新 int min = INT_MAX; int next = -1; for (int i = 0; i < siz; ++i) { if (visited[i]==1) continue; if (vec[source][i] < dist[i]) { prev[i] = source; dist[i] = vec[source][i]; } if (dist[i] < min) { min = dist[i]; next = i; } } --nodeleave; res.push_back(next); source = next; visited[source] = 1; } for (int i = 0; i < siz; ++i) { cout << res[i] << "\t"; } cout << endl; for (int i = 0; i < siz; ++i) { cout << prev[i] << "\t"; } cout << endl; }
//main.cc
#include "Prim.h" #include <stdlib.h> #include <iostream> using namespace std; int main() { vector< vector<int> > input = { { 0, 6, 1, 5, INT_MAX, INT_MAX }, { 6, 0, 5, INT_MAX, 3, INT_MAX }, { 1, 5, 0, 5, 6, 4 }, { 5, INT_MAX, 5, 0, INT_MAX, 2 }, { INT_MAX, 3, 6, INT_MAX, 0, 6 }, { INT_MAX, INT_MAX, 4, 2, 6, 0 } }; Prim(input, 0); //system("pause"); return 0; }
相关文章推荐
- 最小生成树(Prim和Kruscal)
- 【prim + kruscal 】 最小生成树模板
- COJ 1036小镇网(最小生成树prim和kruscal)
- 最小生成树 prim kruscal
- HDU 1863 畅通工程 (最小生成树--Kruscal、Prim)
- poj 1287 Networking(prim or kruscal最小生成树)
- 图的邻接矩阵表示形式,DFS和BFS,最小生成树Prim和Kruscal,单源最短路径Dijkstra算法
- poj 2075 最小生成树 kruscal与prim
- Nyoj 38 布线问题[最小生成树(Prim&&Kruscal)]
- 修路问题-最小生成树 Prim&Kruscal
- poj 2485 Highways(kruscal or prim最小生成树)
- HDOJ 1162 Eddy's picture 最小生成树 Kruscal && Prim
- hdu1162(最小生成树 prim or kruscal模板)
- POJ 2349 Arctic Network(最小生成树 kruscal or prim)
- hdu_1233_畅通工程再续_最小生成树_kruscal_prim
- 【HDU 4463 Outlets】最小生成树(prim,kruscal都可)
- ZOJ 1203 Swordfish 最小生成树 Kruscal && Prim
- 最小生成树之PRIM及KRUSCAL
- poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)
- POJ 2349 Arctic Network 最小生成树 prim && kruscal