最小生成树

最小生成树(Minimal Spanning Tree,MST)

包含图中n个点和边权和最小的n-1条边 的一棵树

Kruskal------ O ( m l o g 2 m ) O(mlog_2m) O(mlog2m)

默认n点数m边数

  • 对从短到长把边 ( u , v ) (u,v) (u,v)放入树中
  • 并查集判圈, u u u作为 v v v的父亲
    如果两点已经在一个并查集中,说明这条边会和之前放入的边形成圈,不放入

模板

cpp 复制代码
const int N = 5e3+10,M=1050;
const double PI=acos(-1);
const long long mod =998244353, inf = 1e18 ;
struct edge
{
  int u,v,w;
};
int n,m;
int fa[N];
vector<edge>e;
int find(int x){
  return fa[x]=(fa[x]==x?x:find(fa[x]));
}
void kruskal(){
  forr(i,1,n)fa[i]=i;
  sort(e.begin(),e.end(),[&](edge x,edge y){
    return x.w<y.w;
  });
  int ans=0,cnt=0;// 长度和 边数<=n-1
  for(auto [u,v,w]:e){
    if(cnt==n-1)break;
    int fu=find(u),fv=find(v);
    if(fu==fv)continue;
    else {// 放入边
      fa[fv]=fu;
      ans+=w;
      cnt++;
    }
  }
  if(cnt==n-1)cout<<ans<<endl;// 能联通所有点
  else cout<<"orz"<<endl;//不连通
}
void solve(){ 
  cin>>n>>m;
  
  forr(i,1,m){
    int x,y,z;
    cin>>x>>y>>z;
    e.push_back({x,y,z});
  }
  kruskal();
}

Prim算法------ O ( m l o g 2 n ) O(mlog_2n) O(mlog2n)

类似Dijkstra 维护一个已加入树的点集 U U U 每次向外拓展一个离点集最近的点

模板

cpp 复制代码
const int N = 5e3+10,M=1050;
const double PI=acos(-1);
const long long mod =998244353, inf = 1e18 ;
int n,m;
vector<pii>e[N];
void prim(){
  int ans=0,cnt=0;
  vector<int>U(n+1,0);
  int bg=1;
  priority_queue<pii>q;
  q.push({0,bg});
  while (q.size())
  {
    auto [dis,now]=q.top();q.pop();
    if(U[now])continue;
    U[now]=1;
    ans+=-dis;
    cnt++;
    for(auto [x,w]:e[now]){
      if(U[x])continue;
      q.push({-w,x});
    }
  }
  
  if(cnt==n)cout<<ans<<endl;
  else cout<<"orz"<<endl;
}
void solve(){ 
  cin>>n>>m;
  
  forr(i,1,m){
    int x,y,z;
    cin>>x>>y>>z;
    e[x].push_back({y,z});
    e[y].push_back({x,z});
  }
  
  prim();
}

例题

蓝桥杯省A 吊坠 最大生成树+环变链 线性dp找最长公共子串

cpp 复制代码
const int N = 205,M=1050;
const double PI=acos(-1);
const long long mod =998244353, inf = 1e18 ;
int n,m;
string s[N];
int find_w(int x,int y){
  vector<vint>dp(2*m+1,vint(2*m+1,0));
  int res=0;
  forr(i,1,2*m){
    forr(j,1,2*m){
      if(s[x][i-1]==s[y][j-1]){
        dp[i][j]=min(dp[i-1][j-1]+1,m);
        res=max(dp[i][j],res);
      }// 注意是子串 子串是连续的
    }
  }
  return res;
}
struct edge
{
  int u,v,w;
};
vector<edge>e;
int fa[N];
int find(int x){
  return fa[x]=(fa[x]==x?x:find(fa[x]));
}
void kruskal(){
  forr(i,1,n)fa[i]=i;
  sort(e.begin(),e.end(),[&](edge x,edge y){
    return x.w>y.w;
  });
  int ans=0,cnt=0;
  for(auto [u,v,w]:e){
    if(cnt==n-1)break;
    int fu=find(u),fv=find(v);
    if(fu==fv)continue;
    fa[fv]=fu;
    cnt++;
    ans+=w;
  }
  cout<<ans<<endl;
}
void solve(){ 
  cin>>n>>m;
  forr(i,1,n){
    cin>>s[i];
    s[i]+=s[i];
  }
  forr(i,1,n){
    forr(j,i+1,n){
      int w=find_w(i,j);
      
      e.push_back({i,j,w});
    }
  }
  kruskal();
}
相关推荐
15Moonlight2 分钟前
C++进阶(09):特殊类设计
开发语言·c++
XiaoYu1__3 分钟前
算法进阶·其一:用SCC、Tarjan算法与缩点思想解决有向图的连通关系及2-SAT问题的拓展
算法
小O的算法实验室6 分钟前
AAAI-26,全局相关性学习:通过谱图神经网络增强进化算法
神经网络·学习·算法
宁风NF7 分钟前
JavaScript:网络请求与前端通信
开发语言·前端·javascript·网络·学习·ecmascript
xqqxqxxq9 分钟前
DML 表数据:插入、删除、修改
笔记·mysql
段一凡-华北理工大学12 分钟前
AI推动工业智能化转型~系列文章07:分类与诊断算法体系:故障识别的完整工具箱
数据库·人工智能·算法·机器学习·分类·数据挖掘·高炉炼铁智能化
简信CRM14 分钟前
适合离散制造中小工厂 MES 系统推荐
算法·机器学习·制造
AKA__Zas14 分钟前
芝士算法(前缀和2.0)
java·数据结构·算法·leetcode·哈希算法·学习方法
皓月斯语29 分钟前
B3867 [GESP202309 三级] 小杨的储蓄 题解
c++·算法·题解