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

算法竞赛备赛——【图论】最小生成树

最小生成树

无向图 连通图才有最小生成树 可以判断图是否连通

记住思路 不要死记模板 灵活建图写代码

Prim算法

由Prim提出。该算法的基本思想是从一个结点开始,不断加点(而不是 Kruskal 算法的加边)。每次总是选出一个离生成树距离最小的点去加入生成树,最后实现最小生成树。类似Dijkstra算法。时间复杂度 O(V^2)------->稠密图

模板

#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
const int inf=0x7fffffff;
int cnt;
struct edge
{int u,w,next;
}e[2*maxn];
int head[maxn];
int dis[maxn];
bool vis[maxn];
int n,m;
void add(int x,int y,int w)		//链式前向星的加点方法
{cnt++;e[cnt].u=y;e[cnt].w=w;e[cnt].next=head[x];head[x]=cnt;
}
int prim()
{for(int i=1;i<=n;i++)dis[i]=inf;dis[1]=0;vis[1]=1;int now=1;for(int i=head[now];i;i=e[i].next)	//链式前向星的遍历方法   可利用堆优化{int u=e[i].u;dis[u]=min(dis[u],e[i].w);}int tot=0;int sum=0;while(tot<n-1){int mindis=inf;for(int i=1;i<=n;i++){if(!vis[i]&&dis[i]<mindis){now=i;mindis=dis[i];}}if(mindis==inf)return -1;//图不连通tot++;sum+=mindis;vis[now]=1;for(int i=head[now];i;i=e[i].next)	//链式前=前向星的遍历方法{int u=e[i].u;if(vis[u])continue;dis[u]=min(dis[u],e[i].w);}}return sum;
}
int main()
{cin>>n>>m;for(int i=1;i<=m;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}int ans=prim();if(ans==-1)printf("orz");else printf("%d",ans);
}

例题

P1265 公路修建 - 洛谷

只能用Prim算法 边有5000*5000

完全图不用存图

设置变量不要用y1,y2,y3…

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
#define INF 1e9
int n;
struct node{int x,y;
}p[5005];
double dis[5005];
int v[5005];
double cal(const node& p1,const node& p2){return (double)sqrt((double)(p1.x-p2.x)*(p1.x-p2.x)+(double)(p1.y-p2.y)*(p1.y-p2.y));//用double 
}int main(){cin>>n;for(int i=1;i<=n;++i){cin>>p[i].x>>p[i].y; }dis[1]=0;v[1]=1;for(int i=2;i<=n;i++){dis[i]=cal(p[1],p[i]);}double minn=INF,ans=0;int k;for(int i=1;i<n;++i){minn=INF;k=-1;for(int j=1;j<=n;++j){if(v[j]==0&&dis[j]<minn){k=j;minn=dis[j];}}v[k]=1;ans+=minn;for(int j=1;j<=n;++j){if(v[j]==0&&dis[j]>cal(p[k],p[j])){dis[j]=cal(p[k],p[j]);}}} printf("%.2lf\n",ans);return 0;
} 

Kruskal算法

Kruskal 算法:由 Kruskal 发明。该算法的基本思想是从小到大加入边,是个贪心算法。在加入边时,需要通过 并查集 来判断该边的两个端点是否属于同一集合(树),避免形成 “环”。时间复杂度 O(ElogE)-----> 稀疏图

模板

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include <climits>
#include<utility>
using namespace std;
const int maxn = 110; // 最大顶点数
const int maxm = 10010; // 最大边数
struct Edge {// 使用结构体储存每一条边,便于排序int u, v, w; // 表示有一条 (u,v) 的无向边,边权为 w
} e[maxm+5];
int ecnt;// 用于边表计数
void addEdge(int u, int v, int w){ // 加入一条无向边++ecnt;e[ecnt].u = u;e[ecnt].v = v;e[ecnt].w = w;
}
int fa[maxn]; // 并查集相关
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]); // 路径压缩
}
int n,m; // 顶点数 边数 
bool cmp(const Edge &a, const Edge &b){return a.w < b.w;
}
int Kruskal() { // Kruskal 算法核心过程for (int i = 1; i <= n; i++) {fa[i] = i; // 初始化并查集}sort (e + 1, e + ecnt + 1, cmp);int sum = 0;for (int i = 1; i <= ecnt; i++) {int u = e[i].u;int v = e[i].v;u = find(u);v = find(v);if (u != v) {fa[u] = v;sum += e[i].w;}}return sum;
}
int main(){scanf("%d %d",&n,&m);int x,y,w;for (int i = 1; i <= m; i++) {scanf("%d %d %d", &x,&y,&w);addEdge(x, y, w);}int ans = Kruskal();printf("%d\n",ans);return 0;
}

例题

P1194 买礼物 - 洛谷

引入虚假的点来转化点权

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int a,b; 
struct Edge{int u,v,w;
}e[300000];
int fa[505];
int cnt;bool cmp(const Edge& x,const Edge& y){return x.w<y.w;
}int find(int x){if(x!=fa[x]) return fa[x]=find(fa[x]);return fa[x];
}int main(){cin>>a>>b;//引入虚假的物品0,买了0再买其他物品for(int i=1;i<=b;++i){e[++cnt].u=0;e[cnt].v=i;e[cnt].w=a;}int k;for(int i=1;i<=b;++i){for(int j=1;j<=b;++j){cin>>k;if(k!=0){e[++cnt].u=i;e[cnt].v=j;e[cnt].w=k;}}}sort(e+1,e+cnt+1,cmp);for(int i=0;i<=b;++i){fa[i]=i;}int x,y,fx,fy,ans=0;for(int i=1;i<=cnt;++i){x=e[i].u;y=e[i].v;fx=find(x);fy=find(y);if(fx!=fy){ans+=e[i].w;fa[fx]=fy;}}cout<<ans<<endl;return 0;
} 
http://www.lryc.cn/news/597120.html

相关文章:

  • Modbus协议详解与c#应用
  • 算法竞赛备赛——【图论】拓扑排序
  • CI/CD与DevOps集成方法
  • python在windows电脑找回WiFi密码
  • 【按下电源键后,电脑里发生了什么?——BIOS:启动世界的“第一把钥匙”】
  • C++编程学习(第14天)
  • [Mediatek] MTK openwrt-21.02 wifi 没启动问题
  • 详述消息队列kafka
  • 【通识】手机和芯片相关
  • LazyVim 加载顺序
  • MySQL金融级数据一致性保障:从原理到实战
  • 数据持久化--PlayerPrefs
  • Hexo - 免费搭建个人博客06 - 安装、切换主题Butterfly
  • 基于Java实现DFT、FFT,并绘制波形图和频谱图,音频播放频谱或波形图
  • 内积(Inner Product)和余弦相似度区别
  • MATLAB近红外光谱分析:MATLAB编程+BP神经网络+SVM+随机森林+遗传算法+变量降维+卷积神经网络等
  • 以 “有机” 重构增长:云集从电商平台到健康生活社区的跃迁
  • 零工合规挑战:盖雅以智能安全体系重构企业用工风控
  • 认识linux进程内存布局以及与命令行参数和环境变量的关系
  • 如何在VS code里使用SQLtool连接上WSL上的MySQL服务
  • 【软件系统架构】系列七:物联网云平台系统性能深入解析
  • 线性神经网络(深度学习-李沐-学习笔记)
  • 探索大语言模型(LLM):提升 RAG 性能的全方位优化策略
  • 我考PostgreSQL中级专家证书二三事
  • 论文略读:REMEDY: RECIPE MERGING DYNAMICS IN LARGE VISION-LANGUAGE MODELS
  • vue3笔记(2)自用
  • 微软2025教育AI报告:教育群体采用AI的比例显著提升
  • 技术速递|使用 Semantic Kernel 与 A2A 协议构建多智能体解决方案
  • Qt 样式表(QSS):打造个性化界面
  • 【前端】【Vue DevTools】Vue DevTools 进阶:用 Trae / Cursor 替换 VSCode 打开文件(跳转行列无误)