算法实践1-2 Kruskal

问题:

Kruskal构造最小生成树的过程。

解析

将所有边存下来,按照权值从小到大排序,然后遍历所有边,每次询问边的两个点是否已经都在最小生成树里了,如果都在,就跳过,否则将其加入,遍历完所有边或者已经形成了最小生成树后结束。

解析图

设计

int kruskal() {
    int ans = 0;
    对边以边权大小为关键字,从小到大排序
    int cnt = 0;
    for (i : e) {
        int u = i.u, v = i.v;
        if (两点都在最小生成树内) continue;
        将u和v加入最小生成树
        cnt++;
        ans += e[i].w;
        if (已经形成了最小生成树) return ans;
    }
    return -1;
}

分析

快排时间复杂度\(O(eloge)\),遍历边时间复杂度\(O(eα(n))\),总时间复杂度\(O(eloge)\)

源码

https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验1-2 Kruskal

#include <bits/stdc++.h>

using namespace std;

const int N = 1e3 + 7;
const int inf = 0x3f3f3f3f;

struct Edge {
    int u, v, w;

    bool operator < (const Edge &a) const {
        return w < a.w;
    }

    Edge () {}
    Edge (int u, int v, int w) : u(u), v(v), w(w) {}
}e[N];

int n, m, u, v, w;
int fa[N], sz[N];

int find(int x) {
    return x == fa[x]? x : fa[x] = find(fa[x]);
}

void merge(int x, int y) {
    x = find(x), y = find(y);
    if (x != y) {
        if (sz[x] < sz[y]) fa[x] = y, sz[y] += sz[x];
        else fa[y] = fa[x], sz[x] += sz[y];
    }
}

int kruskal() {
    int ans = 0;
    sort(e + 1, e + 1 + m);
    int cnt = 0;
    for (int i = 1; i <= m; ++i) {
        int u = e[i].u, v = e[i].v;
        if (find(u) == find(v)) continue;
        merge(u, v);
        cnt++;
        ans += e[i].w;
        if (cnt == n - 1) return ans;
    }
    return -1;
}

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        fa[i] = i;
        sz[i] = 1;
    }
    for (int i = 1; i <= m; ++i) {
        scanf("%d %d %d", &u, &v, &w);
        e[i] = Edge(u, v, w);
    }
    printf("%d\n", kruskal());
    return 0;
}
/*
4 5
1 2 4
1 3 6
1 4 3
2 3 1
2 4 2
*/
posted @ 2021-03-15 09:27  stff577  阅读(43)  评论(0)    收藏  举报