[模板] 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)\)

posted @ 2020-05-27 08:43  ChPu437  阅读(111)  评论(2编辑  收藏  举报