标签:const int Kruskal d% 最小 算法 edge 复杂度
AcWing 859
最小生成树的定义:
给定一张边带权的无向图 \(G=(V,E)\),其中 \(V\) 表示图中点的集合,\(E\)表示图中边的集合,\(n=|V|\),\(m=|E|\)
由$ V$ 中的全部 \(n\) 个顶点和 \(E\) 中 \(n−1\) 条边构成的无向连通子图被称为 \(G\) 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 \(G\) 的最小生成树。
然后我们看Kruskal的算法思想
1.将所有边按照权重从小到大排序,时间复杂度为\(O(m\log m)\)
2.枚举每条边\(a,b\)的权重\(c\),如果\(a,b\)不连通的话,我们就把这一条边添加到集合当中。并查集实现合并、查询,时间复杂度\(O(m)\)
时间复杂度是很快的,所以在稀疏图当中,用\(Kruskal\)就可以了。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200010;
int n,m;
int p[N];//并查集的数组
struct Edge{
int a,b,w;
bool operator < (const Edge &W) const//重载运算符,用于后面排序
{
return w < W.w;
}
}edge[N];
int find(int x) // 并查集
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i ++ )
{
int a,b,w;
scanf("%d%d%d", &a, &b, &w);
edge[i] = {a,b,w};
}
sort(edge, edge + m);
for (int i = 1; i <= n; i ++ ) p[i] = i;
int res = 0;// 最小生成树里的所有权重之和
int cnt = 0;//当前加了多少条边
for (int i = 0; i < m; i ++ )
{
int a = edge[i].a, b = edge[i].b, w = edge[i].w;
a = find(a), b = find(b);//并查集查找根节点
if(a != b)
{
p[a] = b;//合并
res += w;
cnt ++ ;
}
}
if(cnt < n - 1) puts("impossible");
else printf("%d",res);
return 0;
}
标签:const,int,Kruskal,d%,最小,算法,edge,复杂度 来源: https://www.cnblogs.com/ljfyyds/p/16490086.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。