【董晓算法】竞赛常用知识之图论2(最小环,最小生成树)

前言:

本系列是学习了董晓老师所讲的知识点做的笔记

董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com)

动态规划系列(还没学完)

【董晓算法】动态规划之线性DP问题-CSDN博客

【董晓算法】动态规划之背包DP问题(2024.5.11)-CSDN博客

【董晓算法】动态规划之背包DP与树形DP-CSDN博客

字符串系列()

【董晓算法】竞赛常用知识之字符串1-CSDN博客

【董晓算法】竞赛常用知识之字符串2-CSDN博客

数据结构系列(未学完)

【董晓算法】竞赛常用知识点之数据结构1-CSDN博客

搜索系列

董晓算法搜索相关题目及模板-CSDN博客

图论系列

【董晓算法】算法知识之图论1(拓扑排序,多种最短路算法)-CSDN博客

无向图的最小环问题

Floyd 算法求最小环

1.Floyd 算法有一个性质:在最外层循环到点k时**(尚未开始k次循环)**dij表示的是从i到j且仅经过编号1~k-第k次循环)的点的最短路(即途经编号之k点的最短路尚未计算)

2.设最小环中编号最大的顶点为k,环上与k相邻的两个点为i,j,则在最外层循环枚举到k时,该环的长度为ans=dij+wik+wki。
3.故在循环时对于每个k枚举满足i<k且j<k 的点对(i,j)优选答案即可。

cpp 复制代码
  cin>>n>>m;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
      if(i!=j) w[i][j]=1e8;
  for(int i=1;i<=m;i++){
    cin>>a>>b>>c;
    w[a][b]=w[b][a]=c;
  }
  memcpy(d,w,sizeof d);
  for(int k=1; k<=n; k++){
    for(int i=1; i<k; i++)
      for(int j=i+1; j<k; j++)
        ans=min(ans,d[i][j]+w[j][k]+w[k][i]);
    for(int i=1; i<=n; i++)
      for(int j=1; j<=n; j++)
        d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
  }

最小生成树

Prim 算法

Prim(普里姆)算法基于贪心思想的最小生成树(MST) 算法

eu存u点的所有邻边的终点和边权。

duu点与圈外邻点的最小距离,visu 标记u点是否出圈。

算法流程类似 Dikstra 算法,不断选距离最小的点出圈,直到圈内为空

1.初始化,所有点都在圈(集合)内vis=0,ds=0,d其它点=+无穷。

2.每次从圈内选取一个距离最小的点 u,打标记移出圈。

3.对u的所有邻点的距离执行更新操作

4.重复2.3步操作,直到圈内为空。

cpp 复制代码
struct edge{int v,w;};
vector<edge> e[N];
int d[N], vis[N];
bool prim(int s){
  for(int i=0;i<=n;i++)d[i]=inf;
  d[s]=0;
  for(int i=1;i<=n;i++){
    int u=0;
    for(int j=1;j<=n;j++)
      if(!vis[j]&&d[j]<d[u]) u=j;
    vis[u]=1; 
    ans+=d[u];
    if(d[u]!=inf) cnt++;
    for(auto ed : e[u]){
      int v=ed.v, w=ed.w;
      if(d[v]>w) d[v]=w;
    }
  }
  return cnt==n;
}
int main(){
  cin>>n>>m;
  for(int i=0; i<m; i++){
    cin>>a>>b>>c;
    e[a].push_back({b,c});
    e[b].push_back({a,c});
  }

Kruskal(克鲁斯卡尔)算法

Kruskal(克鲁斯卡尔)算法利用并查集求最小生成树(MST)

ei 存第i条边的起点、终点与边权

fax 存x点的父节点。

1.初始化并查集,把n个点放在几个独立的集合

2.将所有的边按边权从小到大排序(贪心思想)。

3.按顺序枚举每一条边,如果这条边连接的两个点不在同一集合就把这条边加入最小生成树,并且合并这两个集合;如果这条边连接的两个点在同一集合一就跳过。

4.重复执行3,直到选取了 n-1条边为止

cpp 复制代码
truct edge{
  int u,v,w;
  bool operator<(const edge &t)const
  {return w < t.w;}   
}e[N];
int fa[N],ans,cnt;

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

对比

相关推荐
依然鸣1 分钟前
PTA团体程序设计天梯赛L2真题讲解L2-045-048
数据结构·c++·经验分享·学习·算法·pat考试·pat
丢掉幻想准备斗争7 分钟前
5.5树与二叉树的应用
算法
ZhouDevin32 分钟前
算法论文/模型微调2——仅骨干1%~3% 参数达到与全量微调相当的性能
算法
Sinosecu-OCR1 小时前
文通OCR技术深度解析:自研算法如何搞定复杂场景识别?
算法·ocr·ocr识别系统
CQU_JIAKE1 小时前
8.5【A】
数据结构·算法
ESBK20251 小时前
学术邀约|CMICA 2026 第二届计算方法、智能控制与航空航天国际会议
大数据·人工智能·算法·飞行器·智能控制·航空航天·计算
无bug代码搬运工2 小时前
LeetCode 42 接雨水:双指针解法详解
算法·leetcode·职场和发展
wuminyu2 小时前
JUC包的AQS与JVM的ObjectMonitor机制对比分析
java·linux·c语言·jvm·c++
Jasmine_llq2 小时前
《P13016 [GESP202506 六级] 最大因数》
数据结构·算法
白狐_7982 小时前
考研408算法设计题保命策略:链表专题暴力解法精讲(2015 & 2019真题实战)
考研·算法·链表