最小生成树算法
来源:互联网 发布:无损歌曲播放软件 编辑:程序博客网 时间:2024/05/29 14:23
常用的最小生成树算法主要有两种,Prim算法和Kruskal算法。
Prim算法的原理是从一个顶点出发,贪心地选取当前点集中权值最小的边,直到所有的点都加入该点集中,算法结束。
Prim算法:
int cost[N][N];//无向图,双向连边,cost[u][v]表示e=(u,v)的权值,不存在时为INF;点从(1,1)开始int mincost[N];//从集合x出发的变道每个顶点的最小权值bool used[N];//顶点i是否已经包含到集合x中int V,E;//V:顶点数;E:边数int Prim(){ for(int i=1; i<=V; i++) { mincost[i]=INF; used[i]=false; } mincost[1]=0; int ans=0; while(true) { int v=-1; for(int u=1; u<=V; u++)//从不属于x的顶点中选取从x到其权值最小的顶点 { if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; } if(v==-1) break; used[v]=true; ans+=mincost[v]; for(int u=1; u<=V; u++)//用与当前点v有连边的点的权值更新最小权值 mincost[u]=min(mincost[u],cost[v][u]); } return ans;}void Init()//初始化{ for(int i=1; i<N; i++) for(int j=1; j<N; j++) cost[i][j]=INF;}
下面的是用优先队列优化的Prim算法:
struct edge /*构建小顶堆*/{ int to; int dis; bool operator < (const edge& t) const { return dis>t.dis; }};priority_queue<edge> q; /*priority_queue q */vector<edge> G[N]; /*graph*/bool vis[N]; /*vis标记数组是否访问*/int V,E; /*vertex edge*/void Init() /*初始化*/{ while(!q.empty()) q.pop(); for(int i=0; i<N; ++i) G[i].clear(); memset(vis,false,sizeof(vis));}void addedge(int from,int to,int cost){ G[from].push_back(edge {to,cost}); G[to].push_back(edge {from,cost});}int priority_queue_prim(){ /*维护一个与1号节点相连的边的集合,然后每次在其中找出最小的边*/ for(int i=0; i<G[1].size(); ++i) { q.push(G[1][i]); } vis[1]=true; /*第一个点标记访问*/ int ret=0; /*统计权值*/ int cnt=V-1; /*所有点是否访问*/ while(!q.empty() &&cnt) { edge p=q.top(); q.pop(); if(vis[p.to]) continue; ret+=p.dis; cnt--; vis[p.to]=true; /*将这条边连接的点加入到1号节点中,然后用新加入节点连接出的几条边去更新优先队列*/ for(int i=0; i<G[p.to].size(); ++i) { edge pp=G[p.to][i]; if(!vis[pp.to]) q.push(pp); } } return ret;}
Kruskal算法的思想是把边的权值从小到大排序,在不产生圈(重边等也算在内)的情况下,把当前的这条边加入生成树中。可以用并查集高效地判断是否是否属于同一个连通分量。
Kruskal算法:
int par[N];//并查集中父亲int hight[N];//并查集树的高度struct edge{ int u,v,cost;};edge G[N];//边集(边数)int V,E;//顶点数和边数//并查集初始化void Init_union_find(int n){ for(int i=0; i<n; i++) { par[i]=i; hight[i]=0; }}//查询树的根int find(int x){ if(par[x]==x) return x; else return par[x]=find(par[x]);}//合并x和y所属的集合void unite(int x,int y){ x=find(x); y=find(y); if(x==y) return ; if(hight[x]<hight[y]) par[x]=y; else { par[y]=x; if(hight[x]==hight[y]) hight[x]++; }}//判断x和y是否属于同一个集合bool same(int x,int y){ return find(x)==find(y);}bool cmp(const edge& a,const edge& b){ return a.cost<b.cost;}int kruskal(){ sort(G,G+E,cmp);//按照edge.cost的顺序从小到大排列 Init_union_find(V);//并查集初始化 int ans=0; for(int i=0; i<E; i++) { edge e=G[i]; if(!same(e.u,e.v)) { unite(e.u,e.v); ans+=e.cost; } } return ans;}
阅读全文
0 0
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树算法
- 最小生成树 算法
- 最小生成树算法
- 数据库概论 --- 完整性约束
- Tablayout设置下划线宽度以及遇到空指针问题。
- Oracle BULK COLLECT INTO批量操作应用
- Java编程:删除 List 元素的三种正确方法
- MySQL存储过程和函数的区别
- 最小生成树算法
- php 简单ioc容器
- PythonStock(1):python 股票系统设计
- 575. Distribute Candies
- mysql中的主外键的理解
- JAVA http请求工具类http-request
- 商品图片放大镜效果
- JS-操作样式
- chrome中加载WebUploader、UEditor,点击上传文件选择框会延迟几秒才会显示,反应很慢