7.26日训练——最小生成树

学习目标:

  • 一天时间掌握kruskal, prim算法原理及模板

学习内容:

  1. prim算法实现原理

  2. prim模板

  3. kruskal算法实现原理

  4. kruskal模板


前言:

不到2小时就AK今天上午比赛,但今天的东西终究只是皮毛,于是自己又找了些类型题做做,明天希望做难题时也能灵光乍现。


prim算法实现原理

假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作:

在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。

此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。

Prim算法的核心:始终保持TE中的边集构成一棵生成树

STEP:

选取任意起点,依次找权值最小的边。

类似于dijkstra的蓝白点阵营思想。


prim模板(堆优化)

int queue_prim (int s,int n) {
    int res = 0;
    vis[s] = 1;
    for(int i = id[s];i;i = e[i].pre)
        q.pnowsh(e[i]);
    for(int i = 1;i < n;i++){
        if(q.size() == 0)break;
        node now = q.top();
        q.pop();
        if(vis[now.to] == 1){
            while(vis[now.to]){
                now = q.top();
                q.pop();
            }
        }
        res += now.cost;
        vis[now.to] = 1;
        for(int j = id[now.to];j;j = e[j].pre){
            if(!vis[e[j].to])q.push(e[j]);
        }
    }
    return res;
}

kruskal算法实现原理

说白了就是按照权值从小到大的顺序选择 n-1 条边,并保证这 n-1 条边不构成回路,首先构造一个只含 n 个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止。

贪心思想。


kruskal模板

#include <bits/stdc++.h>
using namespace std;
int fa[500005];
long long ans = 0;
int n, m;
struct node {
    int x, y, z;
} a[500005];
int Find(int x) {
    if (fa[x] == x)
        return x;
    else
        return fa[x] = Find(fa[x]);
}
bool cmp(node a, node b) { return a.z < b.z; }

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n + 5; i++) {
        fa[i] = i;
    }
    for (int i = 1; i <= m; i++) {
        cin >> a[i].x >> a[i].y >> a[i].z;
    }
    sort(a + 1, a + m + 1, cmp); // 按权值从小到大排序
    for (int i = 1; i <= m; i++) {
        int b = Find(a[i].x);
        int c = Find(a[i].y);
        if (b != c)
            fa[b] = c, ans += a[i].z;
    }
    cout << ans;
}

小结

知识的巩固需要时间,明天也要继续加油(ง •_•)ง。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值