最小生成树的两种算法及模版整理
2014-08-20 15:42
253 查看
图伦的算法是我觉得最高大上的,因为每个算法都有一个很叼的名字!
哈哈,陆续整理一些自己的模版,方便自己以后使用吧。
首先是Prim算法的普通版本 复杂度O(V^2)
然后是prim版本的优先队列优化,复杂度变为O(ElogV)
Prim算法的结构其实跟Dijkstra求最短路特别像,连优化都差不多。。
下面是Kruskal算法,一个贪心算法,每次加入边权最短的边,并且保持树结构(用并查集)。很容易理解,也很好写。
上面用了三种图的存储方式,邻接矩阵,邻接表,还有vector存(类似邻接表)。用法都是可以互换的。针对结点和边的个数进行选择。
哈哈,陆续整理一些自己的模版,方便自己以后使用吧。
首先是Prim算法的普通版本 复杂度O(V^2)
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int INF = 0x3f3f3f3f; int n; int g[105][105]; int vis[105],d[105]; int prim(){ memset(vis,0,sizeof(vis)); memset(d,0x3f,sizeof(d)); int ans = d[1] = 0; for(int i=1;i<=n;i++){ int k = 0,minn = INF; for(int j=1;j<=n;j++)if(!vis[j] && d[j] < minn) minn = d[j],k = j; if(k == 0)break; vis[k] = 1; ans += minn; for(int j=1;j<=n;j++) if(!vis[j]&&g[k][j]&&d[j]>g[k][j]) d[j] = g[k][j]; } return ans; } int main() { while(scanf("%d",&n)==1){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&g[i][j]); printf("%d\n",prim()); } return 0; }
然后是prim版本的优先队列优化,复杂度变为O(ElogV)
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int N = 100005; struct edge{ int v,w,next; bool operator <(const edge &a) const{ return w> a.w; } }node ,t1,t2; int dis ,vis ,head ,cnt; void init(){ memset(vis,0,sizeof(vis)); memset(node,0,sizeof(node)); memset(head,-1,sizeof(head)); memset(dis,0x3f,sizeof(dis)); } void addedge(int u,int v,int w){ node[cnt].v = v; node[cnt].next = head[u]; node[cnt].w = w; head[u] = cnt++; } int prim(){ int ret=0; priority_queue<edge> q; for(int i=head[0];i!=-1;i = node[i].next){ int v = node[i].v; if(node[i].w<dis[v]){ dis[v] = node[i].w; t1.w = dis[v]; t1.v = v; q.push(t1); } } vis[0] = 1; while(!q.empty()){ t1 = q.top(); q.pop(); int u = t1.v; if(vis[u])continue; vis[u] = 1; ret += dis[u]; for(int i=head[u];i!=-1;i = node[i].next) { int v = node[i].v; if(!vis[v] && dis[v] > node[i].w){ dis[v] = node[i].w; t2.v = v; t2.w = dis[v]; q.push(t2); } } } return ret; } int main() { printf("我TM就是个模版。。\n"); return 0; }
Prim算法的结构其实跟Dijkstra求最短路特别像,连优化都差不多。。
下面是Kruskal算法,一个贪心算法,每次加入边权最短的边,并且保持树结构(用并查集)。很容易理解,也很好写。
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; struct edge{ int u, v, w; edge() {} edge(int _u, int _v, int _w):u(_u), v(_v), w(_w) {} }t1; int cmp(edge a,edge b){return a.w<b.w;} vector<edge> e; int n,fa[105]; int findset(int x){ return fa[x] !=x? fa[x] = findset(fa[x]):x; } int Kruskal(){ sort(e.begin(),e.end(),cmp); for(int i=1;i<=n;i++)fa[i] = i; int ret = 0; for(int i=0;i<e.size();i++){ int u = e[i].u,v = e[i].v,w = e[i].w; u = findset(u),v = findset(v); if(u == v)continue; fa[u] = v; ret+=w; } return ret; } int main() { while(scanf("%d",&n)==1){ e.clear(); int temp; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&temp); if(temp)e.push_back(edge(i,j,temp)); } printf("%d\n",Kruskal()); } return 0; }
上面用了三种图的存储方式,邻接矩阵,邻接表,还有vector存(类似邻接表)。用法都是可以互换的。针对结点和边的个数进行选择。
相关文章推荐
- hdu 1233 还是畅通工程(最小生成树的Prim和Kruskal两种算法的c++实现)(prim算法详解)
- 基于c#的两种最小凸包的生成(三硬币法与串行算法)
- 图的深度优先搜索和广度优先搜索算法、最小生成树两种算法 --C++实现
- Kruscal(最小生成树)算法模版
- 还是畅通工程 - 两种经典最小生成树算法的实战
- 最小生成树的两种算法
- [Sicily 1090 Highways] 求最小生成树的两种算法(普里姆算法/克鲁斯卡尔算法)
- 最小生成树-两种算法复杂度比较 poj-1258,2485
- 图的最小生成树的两种算法
- 最小生成树的两种最基本的算法
- 重拾算法(5)——最小生成树的两种算法及其对比测试
- 树:最小生成树-两种算法
- hdu 1863 畅通工程 最小生成树模板入门题 prim+kruskal两种算法AC。
- 浅谈最小生成树的两种算法
- 最小有向生成树--朱刘算法模版(LRJ)
- 最小生成树两种算法。kruskal和prim
- 最小生成树的两种算法:Prim和Kruskal算法
- 最小生成树的两种算法
- (搬运) poj 1751(Highways)+最小生成树两种算法
- hdu1102 Constructing Roads(两种基础最小生成树算法)