当前位置: 首页 > wzjs >正文

银川建网站网站开发的类型

银川建网站,网站开发的类型,四川省级建设主管部门网站,免费进入电影网站人人网入口C最小生成树算法详解 引言 在图论中,最小生成树(Minimum Spanning Tree, MST)是一个非常重要的概念。对于给定的带权无向连通图,最小生成树是一棵包含图中所有顶点且边权之和最小的树。它在网络设计、电路布线等实际应用中具有广泛…

C++最小生成树算法详解

引言

在图论中,最小生成树(Minimum Spanning Tree, MST)是一个非常重要的概念。对于给定的带权无向连通图,最小生成树是一棵包含图中所有顶点且边权之和最小的树。它在网络设计、电路布线等实际应用中具有广泛的意义。本文将详细介绍两种常见的最小生成树算法:Prim算法和Kruskal算法,并提供C++实现代码。

一、最小生成树的基本概念

1.1 生成树

一个连通图的生成树是指一个连通子图,它包含图中的所有顶点,但只有足以构成一棵树的边(即没有回路)。对于有nnn个顶点的连通图,其生成树有n−1n-1n1条边。

1.2 最小生成树

在带权图中,最小生成树是所有生成树中边权之和最小的那棵。最小生成树可能不唯一,但其边权之和一定是最小的。

二、Prim算法

2.1 算法思想

Prim算法是一种贪心算法,其基本思想是从一个任意选择的起始顶点开始,逐步将距离当前生成树最近的顶点加入到生成树中,直到所有顶点都被包含为止。具体来说,算法维护一个优先队列(或最小堆),用来存储尚未访问的顶点及其与当前生成树的最短距离。每次从优先队列中取出距离最小的顶点,并将其加入到生成树中,同时更新与其相邻顶点的距离。

2.2 算法步骤

  1. 初始化:选择一个起始顶点,将其标记为已访问,并将其所有邻接边加入优先队列。
  2. 迭代过程:从优先队列中取出距离最小的顶点,如果该顶点未被访问过,则将其标记为已访问,并将该边加入到最小生成树中。然后,将该顶点的所有邻接边加入优先队列。
  3. 终止条件:当优先队列为空或所有顶点都被访问时,算法结束。此时,已经找到了最小生成树。

2.3 C++实现

以下是Prim算法的C++实现代码:

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<int, int> pii;const int INF = 0x3f3f3f3f;
const int MAXN = 5005;int n, m, u, v, w, cnt, len;
ll sum;
bool vis[MAXN]; // 记录点是否已经在图中
int dis[MAXN][MAXN]; // 距离矩阵
vector<int> tos[MAXN];struct cmp {bool operator()(pii a, pii b) {return a.first > b.first;}
};int main() {cin >> n >> m;memset(dis, 0x3f, sizeof dis);while (m--) {cin >> u >> v >> w;dis[u][v] = min(w, dis[u][v]);dis[v][u] = dis[u][v];tos[u].push_back(v);tos[v].push_back(u);}// 任选一点作为起点,以1为例cnt = 1;vis[1] = true;len = tos[1].size();priority_queue<pii, vector<pii>, cmp> pq;for (int i = 0; i < len; i++) {pq.push(pii(dis[1][tos[1][i]], tos[1][i]));}// 加完了所有点或已经用完了所有边退出while (cnt != n && !pq.empty()) {pii tmp = pq.top();pq.pop();v = tmp.second;if (!vis[v]) {cnt++;vis[v] = true;sum += tmp.first;len = tos[v].size();for (int i = 0; i < len; i++) {if (!vis[tos[v][i]]) {pq.push(pii(dis[v][tos[v][i]], tos[v][i]));}}}}if (cnt == n) {cout << sum << endl;} else {cout << "orz\n"; // 表示无法生成最小生成树}return 0;
}

2.4 代码解释

  • dis数组用于存储图的邻接矩阵,表示顶点之间的边权。
  • tos数组用于存储每个顶点的邻接顶点列表。
  • vis数组用于标记顶点是否已经被访问过。
  • pq是一个优先队列,用于存储尚未访问的顶点及其与当前生成树的最短距离。
  • 算法从顶点111开始,逐步将距离最小的顶点加入到生成树中,并更新与其相邻顶点的距离。

三、Kruskal算法

3.1 算法思想

Kruskal算法也是一种贪心算法,其基本思想是按照边权值从小到大依次选择边,如果这条边的两个端点不在同一个连通块中,就把这条边加入到最小生成树的边集合中。具体来说,算法使用并查集(Disjoint Set Union, DSU)来维护顶点的连通性。

3.2 算法步骤

  1. 初始化:将所有边按照权值从小到大排序,并初始化一个空的最小生成树和一个并查集。
  2. 选择边:从排序后的边集合中选择权值最小的边,检查该边的两个顶点在并查集中是否属于同一个连通分量。如果不属于同一个连通分量,则将该边加入到最小生成树中,并将两个顶点所在的连通分量合并。
  3. 重复步骤2:直到所有顶点都被连接起来,或者已经选择了n−1n-1n1条边(nnn是顶点数),此时得到的树就是最小生成树。

3.3 C++实现

以下是Kruskal算法的C++实现代码:

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<int, int> pii;const int MAXN = 5005;int n, m, u, v, w, cnt;
ll sum;
int pre[MAXN];struct edg {int u, v, w;
};struct cmp {bool operator()(edg e1, edg e2) {return e1.w > e2.w;}
};int findroot(int x) {int r = x, tmp;while (r != pre[r]) {r = pre[r];}while (r != pre[x]) {tmp = pre[x];pre[x] = r;x = tmp;}return r;
}void join(int x, int y) {int fx = findroot(x), fy = findroot(y);if (fx != fy) {pre[fx] = fy;}
}int main() {cin >> n >> m;vector<edg> edges;while (m--) {cin >> u >> v >> w;edges.push_back({u, v, w});}sort(edges.begin(), edges.end(), cmp());for (int i = 1; i <= n; i++) {pre[i] = i;}for (auto &e : edges) {u = e.u;v = e.v;w = e.w;if (findroot(u) != findroot(v)) {cnt++;sum += w;join(u, v);}if (cnt == n - 1) {break;}}if (cnt == n - 1) {cout << sum << endl;} else {cout << "orz\n"; // 表示无法生成最小生成树}return 0;
}

3.4 代码解释

  • edges向量用于存储图的所有边。
  • pre数组用于实现并查集,表示每个顶点的父节点。
  • findroot函数用于查找顶点的根节点,并进行路径压缩。
  • join函数用于合并两个顶点的连通分量。
  • 算法首先将所有边按照权值从小到大排序,然后依次选择边,如果该边的两个顶点不在同一个连通分量中,则将其加入到最小生成树中,并合并这两个连通分量。

四、算法比较与选择

4.1 时间复杂度

  • Prim算法:使用邻接矩阵实现的时间复杂度为O(n2)O(n^2)O(n2),使用堆优化后的时间复杂度为O((V+E)×log⁡2V)O((V + E) \times\log_2 V)O((V+E)×log2V),其中VVV是顶点数,EEE是边数。对于稠密图,Prim算法的效率较高。
  • Kruskal算法:时间复杂度主要由边的排序和并查集操作决定,边排序的时间复杂度为O(E×log⁡2E)O(E \times\log_2 E)O(E×log2E),并查集操作的时间复杂度为O(α(n))O(\alpha(n))O(α(n)),其中α(n)\alpha(n)α(n)是反阿克曼函数,几乎可以认为是常数。因此,Kruskal算法的时间复杂度为O(E×log⁡2E)O(E \times\log_2 E)O(E×log2E)。对于稀疏图,Kruskal算法的效率较高。

4.2 空间复杂度

  • Prim算法:需要存储图的邻接矩阵或邻接表,空间复杂度为O(V2)O(V^2)O(V2)O(V+E)O(V + E)O(V+E)。使用堆优化后,还需要额外的O(V)O(V)O(V)空间来存储优先队列。
  • Kruskal算法:需要存储所有边,空间复杂度为O(E)O(E)O(E),以及并查集的空间开销O(V)O(V)O(V)

4.3 适用场景

  • Prim算法:适用于稠密图,即边数接近顶点数平方的情况。因为在这种情况下,Prim算法的时间复杂度较低。
  • Kruskal算法:适用于稀疏图,即边数相对较少的情况。因为在这种情况下,Kruskal算法的时间复杂度较低。

五、总结

最小生成树是图论中的一个重要概念,Prim算法和Kruskal算法是两种常见的求解最小生成树的算法。Prim算法适合稠密图,而Kruskal算法适合稀疏图。在实际应用中,可以根据图的具体情况选择合适的算法。通过本文的介绍和C++实现代码,希望读者能够更好地理解和应用这两种算法。


附:

α(n)\alpha(n)α(n)函数相关内容如下:

定义与性质

  • 定义:反阿克曼函数α(x)\alpha(x)α(x)定义为最大的整数mmm,使得Ackermann函数A(m,m)≤xA(m, m)\leq xA(m,m)x。由于阿克曼函数的增长速度极快(比指数级还快),其反函数α(x)\alpha(x)α(x)的增长则非常缓慢。

  • 增长特性:对于可以想象到的nnnα(n)\alpha(n)α(n)通常都是在555之内的,这意味着反阿克曼函数增长极为缓慢,几乎可以看作是一个常数。

计算方法

要找到阿克曼函数的反函数,即α(n)\alpha(n)α(n),可以通过观察阿克曼函数的增长模式来设计一个近似算法。为了达到O(log⁡2n)O(\log_2 n)O(log2n)的时间复杂度,可以采用二分查找的思想。首先猜测一个中间值mmm,然后检查A(m,m)A(m, m)A(m,m)是否小于或等于nnn。如果大于,则在左半区间继续搜索;如果小于或等于,就在右半区间继续搜索。每次都将搜索范围减半,直到找到满足条件的最大mmm或者搜索范围变得足够小。

应用场景

  • 并查集算法:在集合的查找过程中顺便将树的深度降低,采用路径压缩后,每一次查询所用的时间复杂度为增长极为缓慢的反阿克曼函数α(x)\alpha(x)α(x)。对于可以想象到的nnnα(n)\alpha(n)α(n)都是在555之内的,因此可以近似看作常数时间复杂度。

文章转载自:

http://Svjnap3k.yqjjn.cn
http://GLxuWMAx.yqjjn.cn
http://ODo52sLa.yqjjn.cn
http://uBqIxgBG.yqjjn.cn
http://SLHIVyhX.yqjjn.cn
http://CAWWD60r.yqjjn.cn
http://SnnbYR06.yqjjn.cn
http://kw4ca0rV.yqjjn.cn
http://Z1iJctwv.yqjjn.cn
http://Peg8Tfmc.yqjjn.cn
http://pWAumIN0.yqjjn.cn
http://UOhI3od4.yqjjn.cn
http://HxEbYUPG.yqjjn.cn
http://uLo7gKKB.yqjjn.cn
http://kL3L2Fg9.yqjjn.cn
http://kOZcImk6.yqjjn.cn
http://cujBrTGo.yqjjn.cn
http://Y16qnvF8.yqjjn.cn
http://Onv6uq5R.yqjjn.cn
http://t937wfkr.yqjjn.cn
http://ft1pLXys.yqjjn.cn
http://T2FhUMdt.yqjjn.cn
http://nW73n8eW.yqjjn.cn
http://PRc2LjFS.yqjjn.cn
http://HsPkobeV.yqjjn.cn
http://TO38snoD.yqjjn.cn
http://tQANcJYy.yqjjn.cn
http://TRz1vdCe.yqjjn.cn
http://d1a4Uj2J.yqjjn.cn
http://hrLDgYtP.yqjjn.cn
http://www.dtcms.com/wzjs/721640.html

相关文章:

  • 网站开发最重要的技巧阿里云网站商城建设
  • 网站制作书籍推荐增城高端定制网站建设
  • 网站建设对工厂意义建设网站的好公司
  • 网站外包 博客wordpress来源转载
  • 做网站找客源p2p网站开发的多少钱
  • 网站seo具体怎么做?深圳 电子商务网站开发
  • 建网站代理有什么做ppt参考的网站
  • 科学小制作小发明seo的培训班
  • 做网站还是做业务员如何建设网站兴田德润实惠
  • 如何帮公司做网站礼品网站制作
  • 做网站收录的网站有哪些热点事件营销案例
  • sentos上部署.net网站施工企业价值链
  • 唐山建设集团招聘信息网站智通人才东莞招聘网
  • 网上买吃的网站做代理济南旅游网页设计
  • 阿里巴巴国际网站首页视频怎么做拼多多推广联盟
  • 移动网站不备案吗qq营销网站源码
  • 离退休工作网站建设方案地方网站域名选择
  • 如何做视频网站赚钱珠宝网站建设需求
  • 手机端网站动效类怎么做网店网站怎么做的
  • 音乐网站禁止做浅度链接wordpress 插件 h5
  • 厦门网站个人制作网站建设为什么要全款
  • 长春建站塔山双喜舆情服务公司
  • 微网站搭建教程应用网站模板
  • 百度收录排名好的网站南京网站制作有限公司
  • 昆明网站建设团队网站建设一般多少钱官网
  • 路由硬盘做网站空间不小程序开发小程序制作
  • 做公司的网站的需求有哪些内容网站的建设与维护需要资质吗
  • 做丝网网站哪个好汉语国际网站建设
  • 医学招聘网站开发区搜索引擎网站分析
  • 怎么做网站收款二维码wordpress付费阅读全文