首页 > 其他分享 >最小生成树

最小生成树

时间:2023-12-27 11:11:38浏览次数:30  
标签:cost int father 最小 生成 ---- Edges 集合

算法思想:kruskal:将边按长度从小到大排序,每次取出一条边并运用并查集检测两点之间是否已经有通路,如果有就不选,如果没有就将该边作为最小生成树的边。Prim:从1顶点开始找距离1最近的点纳入集合并更新其他点距离该集合点的距离,每次选距离集合最短路径纳入集合,直到边数等于n-1。

主要/核心函数分析:float kruskal(int n, int m):将边按长度从小到大排序,每次取出一条边并运用并查集检测两点之间是否已经有通路,如果有就不选,如果没有就将该边作为最小生成树的边,将边的编号纳入最小生成树路径的数组中。void prim():将1纳入集合,每次选取距离集合最近的点纳入集合,最后再更新其他点到集合的距离(同时记录该点到集合中哪个点最短便于路径的输出)。

测试数据:

4 4

1 2 1

2 3 4

2 4 2

3 4 3

运行结果:

边:

1----2

2----4

3----4

KrusKal的最小权值:6

边:

2----1

4----2

3----4

Prim的最小权值:6

时间复杂度:Prim是O(点数的平方);Kruskal是O(边数*log边数)

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include <fstream>
  5 using namespace std;
  6 
  7 const int N = 1002;//点数
  8 const int M = 100002;//边
  9 const int INF = 100000;
 10 int n, m;//输入点数和边数
 11 int index[N];//存储生成树的边
 12 
 13 int a[N][N];
 14 bool visit[N] = {};//节点是否已经被访问 
 15 int dist[N];//顶点与集合的距离
 16 int knot[N]={0};//顶点与集合中哪一点距离最短
 17 
 18 struct edge
 19 {
 20     int x, y;//起点和终点
 21     float cost;
 22 }Edges[M];//边 
 23 
 24 int father[N];//并查集
 25 
 26 int findfather(int x)
 27 {
 28     int a = x;
 29     int z;
 30 
 31     //到这条边最初的起点
 32     while (x != father[x])
 33         x = father[x];
 34 
 35     //路径压缩
 36     while (a != father[a])
 37     {
 38         z = a;
 39         a = father[a];
 40         father[z] = x;
 41     }
 42 
 43     return x;
 44 }
 45 
 46 //比较权值
 47 bool compare(edge a, edge b) { return a.cost < b.cost; }
 48 
 49 float kruskal(int n, int m)
 50 {
 51     float sum = 0;
 52     int edgenum = 0;//权和点数
 53     
 54     for (int i = 1; i <= n; i++)
 55         father[i] = i;
 56     //初始化并查集
 57 
 58     sort(Edges, Edges + m, compare);//从小到大排序
 59 
 60     for (int i = 0; i < m; i++)
 61     {
 62         //判断该条边起点和终点在该边未加入时是否连通
 63         int fax = findfather(Edges[i].x);
 64         int fay = findfather(Edges[i].y);
 65 
 66         //不连通则可以加入
 67         if (fax != fay)
 68         {
 69             father[fax] = fay;
 70             sum += Edges[i].cost;
 71             index[edgenum++]=i;
 72             if (edgenum == n - 1)break;//找到最小生成树
 73         }
 74     }
 75     return sum;
 76 }
 77 
 78 void prim()
 79 {
 80     fill(dist, dist + N, INF);//赋初值
 81     dist[1] = 0;//将1顶点纳入生成树
 82     
 83     float sum = 0;//总费用
 84 
 85     cout << "边:" << endl;
 86     //找最小距离
 87     for (int i = 1; i <= n; i++)
 88     {
 89         int minx = -1;//记录顶点
 90         int mini = INF;//记录距离
 91 
 92         for (int j = 1; j <= n; j++)
 93         {
 94             if (visit[j] == false && dist[j] <= mini)
 95             {
 96                 minx = j;
 97                 mini = dist[j];
 98             }
 99         }//找到与当前集合距离最近的节点 
100 
101         if (minx != -1)//找到符合条件的点
102         {
103             visit[minx] = true;//第minx号点已经访问过了
104             sum += dist[minx];//加入最小生成树,该点加入集合 
105             if (i != 1)
106                 cout << minx << "----" << knot[minx] << endl;
107         }
108 
109         //更新剩余的点到集合的最短距离
110         for (int y = 1; y <= n; y++)
111         {
112             if (visit[y] == false && a[minx][y] != INF && a[minx][y] < dist[y])
113             {
114                 dist[y] = a[minx][y];
115                 knot[y] = minx;
116             }
117         }
118     }
119     cout<<"Prim的最小权值:"<<sum;
120 }
121 
122 int main()
123 {
124     fstream fp;
125     fp.open("test.txt", ios::in);
126 
127     fp >> n >> m;//初始化输入     
128     fill(a[0], a[0] + N * N, INF);//初始化
129     for (int i = 0; i < m; i++)
130     {
131         fp >> Edges[i].x >> Edges[i].y >> Edges[i].cost; //初始化输入边    
132         a[Edges[i].x][Edges[i].y] = a[Edges[i].y][Edges[i].x] = Edges[i].cost;
133     }
134     fp.close();
135 
136     float quanzhi1=kruskal(n,m);
137     cout << "边:" << endl;
138     for (int i = 0; i < n - 1; i++)
139         cout << Edges[index[i]].x << "----" << Edges[index[i]].y << endl;
140     cout << "KrusKal的最小权值:" << quanzhi1 << endl;
141 
142     prim();
143 
144     return 0;
145 }

 

标签:cost,int,father,最小,生成,----,Edges,集合
From: https://www.cnblogs.com/saucerdish/p/17930138.html

相关文章

  • 在 IIS 上生成经典 ASP 网站
    场景:在IIS上生成经典ASP网站本文档将指导你完成安装IIS和配置经典ASP网站的过程。经典ASP是服务器端脚本环境,可用于创建和运行动态Web应用程序。借助ASP,你可以将HTML页面、脚本命令和COM组件组合在一起,从而创建易于开发和修改的交互式网页。经典ASP是ASP.......
  • API文档生成!超好用API调试工具
    在数字化时代,API已经成为了应用程序之间进行通信的关键桥梁。随着API的普及和复杂性的增加,API研发和管理也面临着越来越多的挑战。为了更好地应对这些挑战,Apipost提供了一整套API研发工具,包括API设计、API调试、API文档和API自动化测试等功能。本文将深入介绍Apipost的优势和特点,助......
  • API文档生成!超好用API调试工具
    在数字化时代,API已经成为了应用程序之间进行通信的关键桥梁。随着API的普及和复杂性的增加,API研发和管理也面临着越来越多的挑战。为了更好地应对这些挑战,Apipost提供了一整套API研发工具,包括API设计、API调试、API文档和API自动化测试等功能。本文将深入介绍Apipost的优势和特点,......
  • Emu2:37亿参数开创多模态生成新篇章
    引言多模态任务在人工智能领域一直是极具挑战性的「技术高地」。智源研究院最近开源发布的新一代多模态基础模型Emu2,在这一领域取得了突破性进展。Emu2以其庞大的37亿参数规模和强大的多模态生成能力,为AI的多模态理解和生成开启了新的篇章。模型概述Emu2是一款大规模自回归生成式多......
  • 人类偏好导向:DPO技术重塑SDXL-1.0图像生成
    引言在AI领域,适应和理解人类偏好一直是技术发展的重要方向。斯坦福大学研究团队最近提出的Diffusion-DPO方法,旨在将这一理念应用于图像生成模型,特别是在文本到图像的转换领域。Huggingface模型下载:https://huggingface.co/mhdang/AI快站模型免费加速下载:https://aifasthub.com/......
  • fluentd根据K8S名称空间自动生成索引
    fluentd示例配置:apiVersion:v1data:containers.input.conf:|-<source>@typetailpath/var/log/containers/*.logpos_file/var/log/fluentd-containers.log.postagkubernetes.*<parse>@typejson......
  • Voc2Json--挑选voc中的类别生成json文件
      importargparseimportjson,shutilimportos,sysimportxml.etree.ElementTreeasETparent=os.path.dirname(os.path.realpath(__file__))gadent=os.path.dirname(parent)sys.path.insert(0,gadent)sys.path.append(gadent)fromutils.toolimportlis......
  • 大语言模型生成模型的源码结构复习
    modeling_gpt2.py:1099iflabelsisnotNone:#movelabelstocorrectdevicetoenablemodelparallelismlabels=labels.to(lm_logits.device)#Shiftsothattokens<npredictnshift_logits=lm......
  • 这儿有一个基于redis生成订单流水号的工具,拿走不谢!
     1importcn.hutool.core.util.RandomUtil;2importcn.hutool.core.util.StrUtil;3importlombok.extern.slf4j.Slf4j;4importorg.springframework.beans.factory.annotation.Autowired;5importorg.springframework.data.redis.core.RedisTemplate;6import......
  • 虚拟技术-时分复用、空分复用、进程状态切换、程序生成过程、进程同步、虚拟内存
    虚拟技术把一个物理实体转换为多个逻辑实体。主要有两种虚拟技术:时(时间)分复用技术   空(空间)分复用技术多进程与多线程:多个进程能在同一个处理器上并发执行使用了 时分复用技术,每个进程轮流占用处理器,每次只执行一小个时间片并快速切换。虚拟内存使用了空分复用......