prim算法的思路 和dijkstra是一样的

每次选取一个最近的点 然后去向新的节点扩张 注意这里的扩张 不再是 以前求最短路时候的到新的节点的最短距离

而是因为要生成一棵树 所以是要连一根最短的连枝 所以关键部分修改一下

dist[u] = min(dist[u], e.cost) --->>e是连接 v 和 u的边

同样地 普同写法O(v^2) 用队列优化后O(E*logV)

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#define MAXV 256
#define MAXE 256
#define INF 0x3f3f3f3f using namespace std;
typedef pair<int,int> P;
int V, E;
//和dijkstra完全一样
//书上写法 O(V^2)
int graph[MAXV][MAXV];
int prim()
{
int dist[MAXV];
int res = ;
bool use[MAXV];
fill(dist, dist+MAXV, INF);
fill(use, use+MAXV, );
dist[] = ;//假定1为源点
while (true)
{
int v = -;
for (int i = ; i <= V; i++)
{
if (!use[i] && (v == - || dist[i] < dist[v])) v = i;//查找离原点最近的点
}
if (v == -) break;
use[v] = true;
res += dist[v];
cout << dist[v] << endl; //打印树枝的情况
for (int i = ; i <= V; i++)
{
dist[i] = min(dist[i], graph[v][i]);//这里是唯一的区别 --->>.但其实 这个dist中的值 最后是有问题的 这样最后dist保存的 是离它最近的一个节点的边的值
//第33行打印的结果之所以正确是因为 按着离原点最近的顺序 向外扩张 在dist改变之前已经打印了 但是打印之后它的值是可能会发生改变的
/*
3).重复下列操作,直到Vnew = V: a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,
而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一); b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
*/
}
}
return res;
} //使用堆维护 再使用prim O(E*logV)
struct Edge
{
int to, cost, next;
Edge() {}
Edge(int to, int cost, int next) : to(to), cost(cost), next(next) {}
}edge[MAXE];
int num = ;
int head[MAXV];
void Add(int from, int to, int cost)
{
edge[num] = Edge(to, cost, head[from]);
head[from] = num++;
} int prim2()
{
int dist[MAXV], res = ;
bool use[MAXV];
fill(use, use+MAXV, false);
fill(dist, dist+MAXV, INF);
priority_queue<P, vector<P>, greater<P> > que;
dist[] = ;//假定1为源点
que.push(P(dist[], ));//first -->距离 second -->编号
while(!que.empty())
{
P p = que.top();
que.pop();
if (!use[p.second])//这个也是那个问题 先前点(作为现在去扩张的点 如果被打印过 就不再去打印它了 总之算法思路就是 从原点开始 让最近的一个点去扩张)
{
res += dist[p.second];
cout << dist[p.second] << endl;
}
use[p.second] = true;
if (dist[p.second] < p.first)
{
continue;
}
int t = head[p.second];
while (t != -)
{
Edge e = edge[t];
if (!use[e.to] && dist[e.to] > e.cost)
{
dist[e.to] = e.cost;
que.push(P(e.cost, e.to));
}
t = e.next;
}
}
return res;
} int main()
{
freopen("in.txt", "r", stdin);
scanf("%d%d", &V, &E);
memset(edge, -, sizeof(edge));
memset(head, -, sizeof(head));
for(int i = ; i <= V; i++)
for (int j = ; j <= V; j++) graph[i][j] = INF;
for (int i = ; i < E; i++)
{
int from, to, cost;
scanf("%d%d%d", &from, &to, &cost);
graph[from][to] = cost;
graph[to][from] = cost;
Add(from, to, cost);
Add(to, from, cost);
}
int ans = prim2();
cout << ans << endl;
}

Kruskal -->> O(E*logV)  思路就更加的简单

将所有的边 排序

贪心地从小到大取 如果连接进一个新的点 就加入树枝的集合中 最终 得到的边的集合就是最小生成树

这里判断是否是新的节点 就是判断连通性 那么就使用并查集非常容易

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAXV 256
#define MAXE 256
#define INF 0x3f3f3f3f
using namespace std; int E, V;
//Kruskal 思路: 按边的角度出发 将边从小到大排序 如果 from to 不再一个连通块中 就可以取这一条边(不会产生环)
struct Edge
{
int from, to, cost;
Edge(){}
Edge(int from, int to, int cost) : from(from), to(to), cost(cost) {}
}edge[MAXE]; int par[MAXV];
int find(int x)
{
if(x == par[x]) return x;
else return par[x] = find(par[x]);
}
void unite(int x, int y)
{
int px = find(x), py = find(y);
if (px == py) return ;
else par[py] = px;
}
bool same(int x, int y)
{
int px = find(x), py = find(y);
return px == py;
} bool cmp(Edge e1, Edge e2)
{
return e1.cost < e2.cost;
} //O(E*logV) -->>对于并查集的操作是logN
int Kruskal()
{
int res = ;
for (int i = ; i <= V; i++) par[i] = i;
sort(edge, edge+E, cmp);
for (int i = ; i < E; i++)
{
Edge e = edge[i];
if (!same(e.from, e.to))
{
cout << e.from << " " << e.to << " : " << e.cost << endl;
res += e.cost;
unite(e.from, e.to);
}
}
return res;
} int main()
{
freopen("in.txt", "r", stdin);
scanf("%d%d", &V, &E);
for (int i = ; i < E; i++)
{
int from, to, cost;
scanf("%d%d%d", &from, &to, &cost);
edge[i] = Edge(from, to, cost);
}
int ans = Kruskal();
cout << ans << endl;
return ;
}

转一篇写的很详细的博客

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html

最小生成树求法 Prim + Kruskal的更多相关文章

  1. 最小生成树(prim&kruskal)

    最近都是图,为了防止几次记不住,先把自己理解的写下来,有问题继续改.先把算法过程记下来: prime算法:                  原始的加权连通图——————D被选作起点,选与之相连的权值 ...

  2. 最小生成树之Prim Kruskal算法(转)

    最小生成树 首先,生成树是建立在无向图中的,对于有向图,则没有生成树的概念,所以接下来讨论的图均默认为无向图.对于一个有n个点的图,最少需要n-1条边使得这n个点联通,由这n-1条边组成的子图则称为原 ...

  3. 最小生成树算法 prim kruskal两种算法实现 HDU-1863 畅通工程

    最小生成树 通俗解释:一个连通图,可将这个连通图删减任意条边,仍然保持连通图的状态并且所有边权值加起来的总和使其达到最小.这就是最小生成树 可以参考下图,便于理解 原来的图: 最小生成树(蓝色线): ...

  4. 数据结构之 图论---最小生成树(prim + kruskal)

    图结构练习——最小生成树 Time Limit: 1000MS Memory limit: 65536K 题目描述  有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的.现在我们想知 ...

  5. 最小生成树算法(Prim,Kruskal)

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  6. 最小生成树之 prim算法和kruskal算法(以 hdu 1863为例)

    最小生成树的性质 MST性质:设G = (V,E)是连通带权图,U是V的真子集.如果(u,v)∈E,且u∈U,v∈V-U,且在所有这样的边中, (u,v)的权c[u][v]最小,那么一定存在G的一棵最 ...

  7. C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)

    1.Prim 算法 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 2.Kruskal 算法 直接寻找最小权值的边来构建最小生成树. 比较: Kruskal 算法主要是针对边来展开,边数 ...

  8. 最小生成树详解 prim+ kruskal代码模板

    最小生成树概念: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里 ...

  9. java实现最小生成树的prim算法和kruskal算法

    在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...

随机推荐

  1. Java-学完一个月总结(javaSe学习路线)

    JavaSe的一个月 第一周 0410 基本数据类型:数据类型的转换:运算符:导入删除项目0411 分支结构if else:switch case ;while0412 do while ;for / ...

  2. Java报表之JFreeChart

    一.JFreeChart简介 JFreeChart是JAVA平台上的一个开放的图表绘制类库.它完全使用JAVA语言编写,是为applications,servlets以及JSP等使用所设计. JFre ...

  3. Bundle的用法

    一.API文档说明 1.介绍 用于不同Activity之间的数据传递 1.重要方法 clear():清除此Bundle映射中的所有保存的数据. clone():克隆当前Bundle containsK ...

  4. laravel的scout包安装及laravel-es包安装

    安装laravel/scout 作用:搜索驱动,可随时更换驱动,上层业务逻辑可不用改变 官网文档:https://laravel-china.org/docs/laravel/5.4/scout/12 ...

  5. Pow挖矿流程

    Pow挖矿流程 POW即工作量的证明,主要特征是客户端需要做一定难度的工作得出一个结果,验证方却很容易通过结果来检查出客户端是不是做了相应的工作. Pow挖矿即不断接入新的Block延续Block C ...

  6. SSAS 系列01- DAX公式常用公式

    计算第一次购买时间 CALCULATE(FIRSTDATE(FactInternetSales[OrderDate]),ALLEXCEPT(FactInternetSales,FactInternet ...

  7. AWS Data Lake Service Stack

  8. Django请求,响应,ajax以及CSRF问题

    二.request对象常用属性: Attribute Description path 请求页面的全路径,不包括域名端口参数.例如: /users/index method 一个全大写的字符串,表示请 ...

  9. 什么是cookie(前段时间看到别人简历上把cookie和localStorage混淆了所以专门又去了解了下)

    在前端面试中,有一个必问的问题:请你谈谈cookie和localStorage有什么区别啊? localStorage是H5中的一种浏览器本地存储方式,而实际上,cookie本身并不是用来做服务器存储 ...

  10. html归纳

      onload的用法 表格属性 定时器(测试能否让for循环暂停5秒) 实现表格的滚动条效果 ① table中th的样式:  white-space: nowrap;  单元格内容不换行:② 设置装 ...