【董晓算法】竞赛常用知识之图论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) 算法

e[u]存u点的所有邻边的终点和边权。

d[u]存u点与圈外邻点的最小距离,vis[u] 标记u点是否出圈。

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

1.初始化,所有点都在圈(集合)内vis=0,d[s]=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)

e[i] 存第i条边的起点、终点与边权

fa[x] 存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 分钟前
外包干了27天,技术退步明显。。。。。
软件测试·面试
梅茜Mercy25 分钟前
数据结构:链表(经典算法例题)详解
数据结构·链表
88号技师28 分钟前
2024年12月一区SCI-加权平均优化算法Weighted average algorithm-附Matlab免费代码
人工智能·算法·matlab·优化算法
IT猿手29 分钟前
多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码
开发语言·人工智能·算法·机器学习·matlab
青春男大29 分钟前
java栈--数据结构
java·开发语言·数据结构·学习·eclipse
88号技师30 分钟前
几款性能优秀的差分进化算法DE(SaDE、JADE,SHADE,LSHADE、LSHADE_SPACMA、LSHADE_EpSin)-附Matlab免费代码
开发语言·人工智能·算法·matlab·优化算法
Zer0_on32 分钟前
数据结构栈和队列
c语言·开发语言·数据结构
一只小bit33 分钟前
数据结构之栈,队列,树
c语言·开发语言·数据结构·c++
马浩同学1 小时前
【GD32】从零开始学GD32单片机 | DAC数模转换器 + 三角波输出例程
c语言·单片机·嵌入式硬件·mcu
我要学编程(ಥ_ಥ)1 小时前
一文详解“二叉树中的深搜“在算法中的应用
java·数据结构·算法·leetcode·深度优先