最小生成树 (学习笔记)(25.11.18)

最小生成树 (学习笔记)

概述

在一个图中,边权最小的生成树,称为最小生成树

实现

Kruskal 算法

是一种贪心算法,先把每个边的边权进行排序,然后用并查集维护一下某两个点连接的信息

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3*5+10;
int n, m, ans=0;

struct edge {
    int u, v, w;
}s[200100];

int fa[N];
int find(int x) {
    if (fa[x]==x) return x;
    return find(fa[x]);
}
void add_f(int x, int y) {
    if (fa[x]==fa[y]) return;
    x = find(x), y = find(y);
    fa[x] = y;
}

bool cmp(edge a, edge b) {
    return a.w<b.w;
}
int main() {
    cin>>n>>m;
    for (int i=1; i<=n; i++) fa[i]=i;
    for (int i=1; i<=m; i++) {
        int x, y, z;
        cin>>x>>y>>z;
        s[i] = {x,y,z};
        // add(x,y,z), add(y,x,z);
    }
    sort(s+1, s+m+1,cmp);
    for (int i=1; i<=m; i++) {
        if (find(s[i].u)!=find(s[i].v)) {
            add_f(s[i].u,s[i].v);
            ans+=s[i].w;
        }
    }
    for (int i=1; i<n; i++) {
        if (find(i)!=find(i+1)) {
            cout<<"orz";
            return 0;
        }
    }
    cout<<ans;
    return 0;
}

prim算法

其实现是从一个点开始加点,而不是Kruskal的加边,实现如下

每一次去选择一个距离最小的节点,然后用新的边去做维护,(与Dij很像)我在S组好像当场创造了这个玩意

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3*5+100;
const int M = 1e5*2+100;
int n, m;

int h[N], cnt=1;
struct edge {
    int to, nxt, w;
}s[M*2];
void add(int u, int v, int w) {
    s[++cnt] = {v,h[u],w};
    h[u] = cnt;
}

struct Edge {
    int u, w;
    bool operator <(const Edge& k) const {return w>k.w;}
};
priority_queue<Edge> q;
bool vis[N];
int ans=0, ans_o=0;
void prim(int x) {
    q.push({x,0});
    while (!q.empty()) {
        int u = q.top().u;
        int w = q.top().w;
        q.pop();
        if (vis[u]) continue;
        vis[u]=1;
        ans+=w;ans_o++;
        for (int i=h[u]; i!=0; i=s[i].nxt) {
            int v = s[i].to, w = s[i].w;
            if (!vis[v]) {
                q.push({v,w});
            }
        }
    }
}
int main() {
    cin>>n>>m;
    for (int i=1; i<=m; i++) {
        int x, y, z;
        cin>>x>>y>>z;
        add(x,y,z), add(y,x,z);
    }
    prim(1);
    if (ans_o!=n) cout<<"orz";
    else cout<<ans;
    return 0;
}
posted @ 2025-11-18 20:02  Yuriha  阅读(2)  评论(0)    收藏  举报