首页 > 其他分享 >最小生成树(prim和kruskal)学习笔记

最小生成树(prim和kruskal)学习笔记

时间:2024-12-11 19:58:10浏览次数:6  
标签:prim int kruskal 最小 笔记 生成 算法 dis define

有两个求最小生成树的算法,prim算法和kruskal算法。这两种算法都可以处理边权为负的情况,并且可以处理有负权回路的情况。接下来会分析一下两个算法的区别。

prim算法

这个算法思路主要是不断向最小生成树中添加点,而这个添加的点是距离生成树最近的点。

这个算法主要用在稠密图里面,因为是不断添加点,所以时间复杂度和边没有关系,就算是稠密图有再多的边,只要点不多就没有问题。

实现 : 稠密图我们可以用邻接矩阵去储存图,所以开个g[i][j],表示从i到j的距离,如果是无向图的话,注意赋值的时候要g[i][j]和g[j][i]都来一遍,我们还需要一个dis[N]数组来记录一下每个点到生成树的距离,首先,我们需要对所有的点都遍历一次,所以最外层有个n次的for循环,对于每次操作,我们必须得找到距离最近的点,并且这个点我们不能加入过,所以我们可以再加一个数组记录一下某个点是否被遍历过,现在是怎么找到距离最近的点呢?定义一个minn变量,初始化为无穷大,如果遍历到的这个点的距离小于minn,就更改minn,这样就ok了,如果最后发现idx(记录距离最小的节点)没有发生改变,说明剩下的点距离都是无穷大了,说明出现了孤立点,它的距离没有被更新,这时候说明这个图没有最小生成树,如果idx被更新了,说明找到了距离最小的点,这时候就得更新其他没有加入过的点到生成树的距离了。还有就是初始化的问题了,dis数组初始化为无穷大,g[i][j]也初始成无穷大。

时间复杂度 : o(n*n)

例题

给定一个 nn 个点 mm 条边的无向图,图中可能存在重边和自环,边权可能为负数。

求最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible

给定一张边带权的无向图 G=(V,E)G=(V,E),其中 VV 表示图中点的集合,EE 表示图中边的集合,n=|V|n=|V|,m=|E|m=|E|。

由 VV 中的全部 nn 个顶点和 EE 中 n−1n−1 条边构成的无向连通子图被称为 GG 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 GG 的最小生成树。

输入格式

第一行包含两个整数 nn 和 mm。

接下来 mm 行,每行包含三个整数 u,v,wu,v,w,表示点 uu 和点 vv 之间存在一条权值为 ww 的边。

输出格式

共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible

数据范围

1≤n≤5001≤n≤500,
1≤m≤1051≤m≤105,
图中涉及边的边权的绝对值均不超过 1000010000。

输入样例:

4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4

输出样例:

6
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define inf 0x3f3f3f3f3f3f3f3f
#define endl "\n"
#define lowbit(x) (x&(-x))
const int N = 510;
int g[N][N];
int dis[N];
bool st[N];
int n,m;
void prim(){
    memset(dis, inf, sizeof dis);
    dis[1] = 0;
    int res = 0;
    for(int i = 1; i <= n; i++){
        int idx = 0, minn = inf;
        for(int j = 1; j <= n; j++){
            if(!st[j]&&dis[j]<minn){
                minn = dis[j];
                idx = j;
            }
        }
        if(idx==0){
            cout << "impossible" << endl;
            return;
        }
        res += dis[idx];
        st[idx] = true;
        for(int j = 1; j <= n; j++){
            if(!st[j]&&dis[j]>g[idx][j]) dis[j] = g[idx][j]; 
        } 
    }
    cout << res << endl;
}
void solve(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++) g[i][j] = inf;
    }
    while(m--){
        int a,b,c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(c,g[a][b]);
    }
    prim();
}
signed main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int T=1;
    //cin >> T;
    while(T--) solve();
    return 0;
}

//
//
//
//
//

我在写代码时出现的问题:g[a][b] = g[b][a] = min(c,g[a][b]); 因为有重边,我们要记录最短的一条,所以这样写,而不是g[a][b] = g[b][a] = c;   还有一个是dis[1] = 0; 因为需要起点的位置更新其他的距离,所以如果忘了这个的话,第一次就更新不了idx,然后就输出impossible了。

kruskal算法

这个算法思路主要是不断向最小生成树中添加边。

这个算法主要用在稀疏图里面,因为是不断添加边,所以时间复杂度和点没有关系,就算是稀疏图有再多的点,只要边不多就没有问题。

思路:我们用结构体去储存每一条边,然后把这些边按边权从小到大排序,然后添加的时候先挑边权小的边添加,每当判断一个边的时候,需要看这条边是否可以与之前已经构建的生成树合成一个环,如果能合成一个环的话,就舍弃这一条边,判断能否合成一个环可以用并查集来判断,并查集储存这个边的两个顶点,如果这两个顶点的代表元素相同,那么这两个顶点可以合成一个环。好奇怪,同一个代码第一次没过,找了一个小时bug,没找到问题,结果第二次过了???

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define inf 0x3f3f3f3f3f3f3f3f
#define endl "\n"
#define lowbit(x) (x&(-x))
const int N = 1e5+10;
int fa[N];
struct E{
    int a,b,c;
    bool operator < (const E& rhs){//通过边长进行排序
        return this->c < rhs.c;
    }
}edg[2*N];
int n,m,res,cnt;
int find(int x){
    if(x==fa[x]) return x;
    else{
        fa[x] = find(fa[x]);
        return fa[x];
    }
}
void ksl(){
    for(int i = 1; i <= m; i++){
       int pa = find(edg[i].a), pb = find(edg[i].b);
       if(pa!=pb){
         res += edg[i].c;
         fa[pa] = pb;
         cnt++; 
       }
    }
    //cout << cnt << endl;
    if(cnt>=n-1) cout << res << endl;
    else cout << "impossible" << endl;
}
void solve(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++) fa[i] = i;
    for(int i = 1; i <= m; i++){
        cin >> edg[i].a >> edg[i].b >> edg[i].c;
    }
    sort(edg+1,edg+1+m);
    ksl();
}
signed main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int T=1;
    //cin >> T;
    while(T--) solve();
    return 0;
}

//
//
//
//
//

结构体排序

bool operator < (const E& tmp){
    return this->c < tmp.c;
}

标签:prim,int,kruskal,最小,笔记,生成,算法,dis,define
From: https://blog.csdn.net/2403_85701606/article/details/144392980

相关文章

  • 《算法设计与分析》学习笔记之一:动态规划
    《算法设计与分析》学习笔记之一:动态规划目录《算法设计与分析》学习笔记之一:动态规划动态规划(dynamicprogramming)钢条切割问题带备忘的自顶向下法(top-downwithmemorization)自底向上法(bottom-upmethod)子问题图解重构矩阵链乘法前置知识求解自底向上表格法动态规划的一般方法......
  • YOLOv8-ultralytics-8.2.103部分代码阅读笔记-model.py
    model.pyultralytics\engine\model.py目录model.py1.所需的库和模块2.classModel(nn.Module): 1.所需的库和模块#UltralyticsYOLO......
  • CS144-Lab0 学习笔记
    编程tip在进行数学运算时,增加中间变量比如boolReader::is_finished()const{returnflag_closed&&buf.size()<=0;}改成boolReader::is_finished()const{boolis_fully_poped=buf.size()<=0;returnflag_closed&&is_fully_poped;}增加中间变......
  • Golang学习笔记_02——函数
    Golang测试功能应用Golang学习笔记_01——包函数文章目录函数1.定义2.返回值3.命名返回值4.可变参数源码Go语言中的函数是一种基本的编程结构,用于封装一段代码,以便在需要时多次调用。函数可以接收参数并返回结果,是实现代码复用和模块化编程的重要手段。1......
  • linux/centOS7用户和权限管理笔记
    linux系列中可以:配置多个用户配置多个用户组用户可以加入多个用户中linux中关于权限的管理级别有2个级别,分别是:针对用户的权限控制针对用户组的权限控制一,root用户root用户拥有最大的系统操作权限,而普通用户在许多地方的权限是受限的二,用户组的管理(root用户执行)1.创建用......
  • linux/centOS7用户和权限管理笔记练习
    1.创建用户组bigdata2.创建用户dsj,指定基本组bigdata,附加组bigdata2,指定home目录为/home/dsj3.查看用户4.创建用户dsj2,指定基本组为bigdata2,附加组为bigdata,指定uid为24025.查看dsj2用户6.从root用户切换到dsj用户7.切回root用户 8.给dsj2用户添加密码 9.......
  • 用户画像--《美团机器学习实践》笔记
    原文:https://cloud.tencent.com/developer/article/2212164最近学习了用户画像方面的内容,本文主要是学习《美团机器学习实践》的读书笔记。 什么是用户画像?用户模型和用户画像的区别。用户模型是指真实用户的虚拟代表,在真实数据的基础上抽象处理的一个用户模型,是产品在描述用......
  • 学习笔记/数学:序理论相关
    鉴于这个神(xie)奇(e)的东西在我眼前晃过的次数已经过多了,于是决定系统的学习一下。本文参考了OI-Wiki序理论,并在此基础上增添了很多个人理解,特此鸣谢。前置知识:集合、基础图论。二元关系定义何为二元关系(binaryrelation)?感性理解,二元关系就是function<bool(T1,T2)>,比如说:......
  • Less学习笔记
    1.概述Less是一款比较流行的css预处理语言,支持变量、混合、函数、嵌套、循环等特点通俗的说CSS预处理器用一种专门的编程语言,进行Web页面样式设计,然后再编译成正常的CSS文件,以供项目使用能够解决CSS重复代码较多的问题2.编译2.1方式1安装node......
  • Visual Autoregressive Modeling(VAR)学习笔记
    paper:2404.02905(arxiv.org)https://arxiv.org/pdf/2404.02905GitHub:GitHub-FoundationVision/VAR:[NeurIPS2024Oral][GPTbeatsdiffusion......