最小生成树

最小生成树(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();
}
相关推荐
生活观察站7 分钟前
中星微端侧芯片,赋能多行业智能化转型落地
数码相机·学习
嵌入式-老费8 分钟前
esp32开发与应用(怎么用好esp32)
学习
大大杰哥11 分钟前
leetcode hot100(3)子串
c++·算法·leetcode
秦明月1312 分钟前
KUKA机器人Profinet通讯实战指南
经验分享·学习·职场和发展·学习方法·设计规范
半导体守望者12 分钟前
MKS ACG-3 XL RF Power Generator OPERATION MANUAL RF 射频电源
学习·机器人·自动化·制造·模块测试
Heartache boy15 分钟前
野火STM32_HAL库版课程笔记-I2C介绍
笔记·stm32·单片机
fish_xk15 分钟前
哈希的了解
算法·哈希算法
水木流年追梦15 分钟前
大模型入门-应用篇1-prompt技术
开发语言·python·算法·prompt
莫生灬灬17 分钟前
ElementUI封装 共91个组件 支持易语言/火山/C#/Python
开发语言·c++·python·ui·elementui·c#
WL_Aurora19 分钟前
【每日一题】位运算
python·算法