当前位置: 首页 > backend >正文

[图论]Prim

Prim

  • 本质:BFS+贪心,对点进行操作。与最短路Dijkstra算法是“孪生兄弟”。
  • 存储结构:链式前向星
  • 适用对象:可为负权图,可求最大生成树
  • 核心思想:最近的邻接点一定在最小生成树(MST)上,对点的最近邻接点贪心。
  • 算法流程:设源点 s s s(任意点),MST已选点集 { S } \set{S} {S}(初始 { S } = ∅ \set{S}=\varnothing {S}=);各点当前到已选点集 { S } \set{S} {S}的最小边权 { d i s } \set{dis} {dis}(初始 { d i s } \set{dis} {dis}:非 s : + ∞ s:+\infty s:+,表示该点目前不可达; s = 0 s=0 s=0);当前MST方案数组 t r e e tree tree(存储其上个源点,初始化为 − 1 -1 1表示无方案),待算法结束后极为最终方案;当前轮起点 U U U U U U邻接点集 { V } \set{V} {V},邻接点权值集 { W } \set{W} {W}
    循环执行下列步骤,直到点集 { S } \set{S} {S}包含所有顶点,或剩余点无法进入 { S } \set{S} {S}
    1. 考查最近顶点(贪心):从全体点集中,找出先前不在 { S } \set{S} {S}中(未被考查)且距点集 { S } \set{S} {S}最近( d i s dis dis最小)的顶点,作为当前轮起点 U U U(首次即为源点 s s s),将其进入 { S } \set{S} {S}(考查顶点 U U U)
    2. 扩散邻接点(BFS扩散):扩散 U U U的邻接点且先前未被考查的顶点 V V V,检查是否能通过 U U U而使其距点集 { S } \set{S} {S}更短( d i s dis dis更小)。若更短,则更新该点 d i s dis dis,并更新路径: d i s [ V ] = m i n ( d i s [ V ] , W ) dis[V]=min(dis[V],W) dis[V]=min(dis[V],W), t r e e [ V ] = U tree[V]=U tree[V]=U
  • Prim算法与最短路算法Dijkstra是“孪生兄弟”。与Dijkstra不同之处在于更新操作中,Prim为更新为所有点到 { S } \set{S} {S}整体的距离(即 d i s [ V ] = m i n ( d i s [ V ] , W ) dis[V]=min(dis[V],W) dis[V]=min(dis[V],W));而Dijkstra为更新所有点到 { S } \set{S} {S}特定一点(源点 s s s)的距离(即 d i s [ V ] = m i n ( d i s [ V ] , d i s [ U ] + W ) dis[V]=min(dis[V],dis[U]+W) dis[V]=min(dis[V],dis[U]+W))。
  • 复杂度:朴素版 O ( V 2 ) O(V^2) O(V2),二叉堆优化版 O ( V log ⁡ 2 E ) O(V\log_2E) O(Vlog2E)
using ll=long long;
using pll=pair<ll,ll>;
const ll INF=__LONG_LONG_MAX__;
ll n,m,s;//点数,边数,源点
struct vertex{int e=-1;
}v[n];
struct edge{int u,v,w,n=-1;
}e[m];

注:若无特殊说明,本文默认顶点均为从0起编号。

朴素版

  • 选目前 d i s dis dis最小点 U U U的3个条件:该点未被考查,该点 d i s dis dis非无穷,该点 d i s dis dis更小
  • 扩散至 U U U邻接点 V V V的3个条件:该邻接点未被考查,边权值 W W W非无穷, V V V通过 U U U而使 d i s dis dis更短
int prim() {vector<bool>S(n,0);vector<ll>dis(n,INF),tree(n,-1);ll s=0,ans=0;dis[s]=0;for (int j=0;j<n;j++){ll U=-1,minn=INF;for(ll i=0;i<n;i++)if(!S[i]&&dis[i]!=INF&&dis[i]<minn) U=i,minn=dis[i];if(U==-1) return -1;//剩余点均不可达,不存在MSTS[U]=1;ans+=dis[U];for (ll i=v[U].e;~i;i=e[i].n){//~i:i!=-1ll V=e[i].v,W=e[i].w;if (!S[V]&&W!=INF&&dis[V]>W)//与Dijkstra唯一不同点dis[V]=min(dis[V],W),tree[V]=U;}}return ans;
}

若求最大生成树: d i s dis dis应初始化为 − ∞ -\infty ;找 d i s dis dis最大顶点;更新条件改为 d i s [ V ] < W dis[V]<W dis[V]<W

二叉堆优化版

优化点:另设顶点的小根堆 Q Q Q,其结构为 { d i s , i n d e x } \set{dis,index} {dis,index},可动态维护当前 d i s dis dis最小点 U U U

另设计数器 c n t cnt cnt,若 c n t < V cnt<V cnt<V,则证明是非连通图,无法构成MST。

  • 选目前 d i s dis dis最小点 U U U的3个条件:该点未被考查,该点 d i s dis dis非无穷,该点 d i s dis dis更小。

  • 扩散至 U U U邻接点 V V V的3个条件:该邻接点未被考查,边权值 W W W非无穷, V V V通过 U U U而使 d i s dis dis更短

int prim() {vector<ll>dis(n,INF),tree(n,-1);vector<bool>S(n,0);priority_queue<pll,vector<pll>,greater<>>pq;int ans=0,cnt=0,s=0;dis[s]=0,pq.push({dis[s],s});//dis,indexwhile(pq.size()){ll U=pq.top().second;pq.pop();if(S[U]) continue;S[U]=1,ans+=dis[U],cnt++;for(ll i=v[U].e;~i;i=e[i].n){//~i:i!=-1ll V=e[i].v,W=e[i].w;if(!S[V]&&W!=INF&&dis[V]>W){//与Dijkstra唯一不同点dis[V]=W,tree[V]=U;pq.push({dis[V],V});}}}if(cnt<n) return -1;return ans;
}

若求最大生成树: d i s dis dis应初始化为 − ∞ -\infty ;维护大根堆;更新条件改为 d i s [ V ] < W dis[V]<W dis[V]<W

http://www.xdnf.cn/news/40.html

相关文章:

  • docker的基础知识
  • 多模态大模型的算力需求预测:从理论FLOPs到实际集群配置(搭建算力成本评估模型的方法论)
  • 每日OJ_牛客_ruby和薯条_排序+二分/滑动窗口_C++_Java
  • 知识库Qanyting部署问题总结
  • 个人博客系统后端 - 用户信息管理功能实现指南(上)
  • Ubuntu利用docker搭建Java相关环境记录(二)
  • C++学习:六个月从基础到就业——面向对象编程:重载运算符(下)
  • 容器docker入门学习
  • ubuntu24.04离线安装deb格式的mysql-community-8.4.4
  • 【C++初阶】--- list容器功能模拟实现
  • 基于flask+vue框架的灯饰安装维修系统u49cf(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 【Unity】JSON数据的存取
  • 燕山大学计算机网络之Java实现TCP数据包结构设计与收发
  • 有什么工具可以在家连接到公司内网?局域网址提供异地公网访问的那些常用方法
  • 一台 Master 多节点玩转 Kubernetes:sealos 一键部署实践
  • MahApps.Metro:专为 WPF 应用程序设计的 UI 框架
  • 【数据结构】AVL树
  • 自动驾驶系列—GLane3D: Detecting Lanes with Graph of 3D Keypoints
  • android liveData observeForever 与 observe对比
  • CS144 Lab0实战记录:搭建网络编程基础
  • 游戏引擎学习第231天
  • 02、GPIO外设(一):基础知识
  • Windows平台使用Docker部署Neo4j
  • 从零上手GUI Guider学习LVGL——Button
  • 【Windows本地部署n8n工作流自动平台结合内网穿透远程在线访问】
  • SAP HANA使用命令行快速导出导入
  • 【HFP】深入解析蓝牙 HFP 协议中呼叫转移、呼叫建立及保持呼叫状态的机制
  • 在 Kali Linux 上安装 Java OpenJDK 8(详细指南)
  • 在Pycharm配置stable diffusion环境(使用conda虚拟环境)
  • Mac idea WordExcel等文件git modify 一直提示修改状态