[模板] Kruskal 求最小生成树
Kruskal求最小生成树
5/27/2020 9:28 更新:原来那个程序有点怪。。已经改了
运用了贪心的思想
最小生成树上的每条边一定是可选的最小边才能最优,其他情况均不是最优
因此将所有边加入小根堆,然后每次取堆顶
并查集维护连通性防止重复加边以及生成环
代码:
// Kruskal
# include <iostream>
# include <cstdio>
# include <queue>
# define MAXN 5005
# define MAXM 200005
using namespace std;
struct edge{
int u, v;
int val;
int next;
bool operator > (const edge that) const{
return this->val > that.val;
}
}e[MAXM<<1], temp;
int head[MAXM<<1], cntEdge;
void addEdge(int u, int v, int val){
e[++cntEdge].u = u, e[cntEdge].v = v, e[cntEdge].val = val;
e[cntEdge].next = head[u], head[u] = cntEdge;
return;
}
priority_queue<edge, vector<edge>, greater<edge> >q;
int fa[MAXN];
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y){
x = find(x);
fa[x] = y;
return;
}
int n, m;
int main(){
int ans = 0;
cin>>n>>m;
for(int i = 1; i <= n; i++)
fa[i] = i;
for(int i = 1; i <= m; i++){
cin>>temp.u>>temp.v>>temp.val;
q.push(temp);
}
for(int i = 1; i <= m; i++){
temp = q.top();
if(!(find(temp.u) == find(temp.v))){
merge(temp.u, temp.v);
ans += temp.val; // 统计总边权
}
q.pop();
}
for(int i = 2; i <= n; i++)
if(find(i) != find(1)){
cout<<"该图不连通!";
return 0;
}
cout<<ans;
return 0;
}
时间复杂度:\(O(E\log E)\)