模版题为【poj 1287】Networking。

题意我就不说了,我就想简单讲一下Kruskal和Prim算法。卡Kruskal的题似乎几乎为0。(●-`o´-)ノ

假设有一个N个点的连通图,有M条边(不定向),求MST(Minimal Spanning Tree)最小生成树的值。

1.Kruskal 克鲁斯卡算法

概述:将边从小到大排序,依次将边两端的不在同一个联通分量/联盟的点分别加入一个个联盟内,将边也纳入,计入答案。最终N个点合并为一个联盟,也就是纳入联盟内的边达到N-1条就结束算法。
实现:并查集。
时间复杂度:O(m log m+m*k)≈O(m log m)
应用:稀疏图(Sparse Graph, 由于主要看边数)
注意——无须建2条双向边,因为每次纳入点,但时间复杂度又是按边算的。
代码如下——

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5 #include<iostream>
6 using namespace std;
7 const int N=110,M=5010,D=10010;
8
9 //这是无向边的图,不用建2倍的便关于方向的边。
10 struct node
11 {
12 int x,y,d;
13 node() {}//
14 node(int x,int y,int d):x(x),y(y),d(d) {}//
15 //bool operator < (const node& now) const
16 //{ return d<now.d; }
17 }a[M];
18 int fa[N];
19 int n,m;
20
21 bool cmp(node x,node y) {return x.d<y.d;}
22 int mmin(int x,int y) {return x<y?x:y;}
23 int ffind(int x)
24 {//保持树的形态不变,顺便把遍历过的结点都改成树根的子节点,而不是之前子节点的子节点(这样要find要调用很多层)
25 if (fa[x]!=x) fa[x]=ffind(fa[x]);
26 return fa[x];
27 }
28 int Kruskal()
29 {
30 int i,k;
31 int x,y,xx,yy;
32 int cnt=0,ans=0;
33 sort(a+1,a+1+m,cmp);
34 for (i=1;i<=n;i++) fa[i]=i;
35 for (i=1;i<=m;i++)//从最小的边开始选
36 {
37 x=a[i].x,xx=ffind(x);
38 y=a[i].y,yy=ffind(y);
39 if (xx!=yy)
40 {
41 cnt++,ans+=a[i].d;
42 fa[xx]=yy;
43 if (cnt==n-1) break;//边选够了
44 }
45 }
46 return ans;
47 }
48 int main()
49 {
50 while (scanf("%d",&n)!=EOF && n)
51 {
52 scanf("%d",&m);
53 int i,x,y,d;
54 for (i=1;i<=m;i++)
55 {
56 scanf("%d%d%d",&x,&y,&d);
57 a[i]=node(x,y,d);//
58 }
59 printf("%d\n",Kruskal());
60 }
61 return 0;
62 }

Kruskal

2.Prim 普里姆算法

概述:先将1个点纳入联盟内,于是每次新纳入离联盟最近的点(看联盟内的点连到联盟外的点的边权),更新距离。

实现:邻接矩阵 或 邻接表+优先队列

时间复杂度:O(n2) & O(m log n)

【别人说邻接表的是O(m log n),还是O(m+n)(??),可我用的是邻接表但并不那么觉得......既然这个算法几乎用不到,我就不深究了。然后我之后发现求SP最短路的Dijkstra 迪杰斯特拉算法除了“更新距离”那里不一样,其他代码都是一模一样的!⊙o⊙ 所以优化后的内容可以参考我的另外一篇的博文了。就是这个:关于最短路径问题(图论)

应用:稠密图(Dense Graph, 由于主要看点数)

注意——由于用到了邻接表的last[]和a[].next,所以要建双向边。

代码如下——(无优化的)

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 using namespace std;
7
8 const int N=55,M=3010,D=110;
9 int n,m,len;
10 struct edge
11 {
12 int x,y,d,next;
13 edge() {}
14 edge(int x,int y,int d):x(x),y(y),d(d) {}
15 }a[M];
16 int dis[N],vis[N],last[N];
17
18 int mmin(int x,int y) {return x<y?x:y;}
19 void ins(int x,int y,int d)
20 {
21 a[++len]=edge(x,y,d);
22 a[len].next=last[x],last[x]=len;
23 }
24 int Prim()
25 {
26 int i,j,k,ans=0;
27 memset(vis,0,sizeof(vis));
28 memset(dis,63,sizeof(dis));//点到联盟的距离
29 dis[1]=0;//candidate
30 for (i=1;i<=n;i++)//每次选一个到联盟距离最小的vertices顶点
31 {
32 int p=0;
33 for (j=1;j<=n;j++)
34 if (!vis[j] && dis[j]<dis[p]) p=j;
35 ans+=dis[p];
36 dis[p]=0,vis[p]=1;
37 for (k=last[p];k;k=a[k].next)//调整
38 {
39 int y=a[k].y;
40 dis[y]=mmin(dis[y],a[k].d);
41 }
42 }
43 return ans;
44 }
45 int main()
46 {
47 int i,x,y,d;
48 while (scanf("%d",&n)!=EOF && n)
49 {
50 scanf("%d",&m);
51 memset(last,0,sizeof(last));
52 len=0;
53 for (i=1;i<=m;i++)
54 {
55 scanf("%d%d%d",&x,&y,&d);
56 ins(x,y,d),ins(y,x,d);
57 }
58 m*=2;
59 printf("%d\n",Prim());
60 }
61 return 0;
62 }

Prim 邻接表

还有一个模版题:【uva 1395】Slim Span(图论--最小生成树+结构体快速赋值 模版题)

关于最小生成树 Kruskal 和 Prim 的简述(图论)的更多相关文章

  1. 最小生成树——Kruskal与Prim算法

    最小生成树——Kruskal与Prim算法 序: 首先: 啥是最小生成树??? 咳咳... 如图: 在一个有n个点的无向连通图中,选取n-1条边使得这个图变成一棵树.这就叫“生成树”.(如下图) 每个 ...

  2. 最小生成树 kruskal算法&prim算法

    (先更新到这,后面有时间再补,嘤嘤嘤) 今天给大家简单的讲一下最小生成树的问题吧!(ps:本人目前还比较菜,所以最小生成树最后的结果只能输出最小的权值,不能打印最小生成树的路径) 本Tianc在刚学的 ...

  3. 最小生成树算法(Prim,Kruskal)

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  4. 稀疏图(邻接链表),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)

    全部函数通过杭电 1142,1162,1198,1213等题目测试. #include<iostream> #include<vector> #include<queue ...

  5. 稠密图(邻接矩阵),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)

    全部函数通过杭电 1142,1162,1198,1213等题目测试. #include<iostream> #include<vector> #include<queue ...

  6. 最小生成树(Kruskal和Prim算法)

    关于图的几个概念定义:          关于图的几个概念定义: 连通图:在无向图中,若任意两个顶点vi与vj都有路径相通,则称该无向图为连通图. 强连通图:在有向图中,若任意两个顶点vi与vj都有路 ...

  7. 1.1.2最小生成树(Kruskal和Prim算法)

    部分内容摘自 勿在浮沙筑高台 http://blog.csdn.net/luoshixian099/article/details/51908175 关于图的几个概念定义: 连通图:在无向图中,若任意 ...

  8. 最小生成树——kruskal算法

    kruskal和prim都是解决最小生成树问题,都是选取最小边,但kruskal是通过对所有边按从小到大的顺序排过一次序之后,配合并查集实现的.我们取出一条边,判断如果它的始点和终点属于同一棵树,那么 ...

  9. 数据结构之最小生成树Kruskal算法

    1. 克鲁斯卡算法介绍 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路. 具体做法:首先构造一个 ...

随机推荐

  1. win10中安装Linux子系统

    前言 Win10的Linux子系统闻名已久,今天就来操作一下 正文 限制 该功能是win10 1809 及之后才加入的功能,故请先核对版本. 开启功能 打开windows设置 设置 -> 更新和 ...

  2. 搭乘“AI大数据”快车,肌肤管家,助力美业数字化发展

    经过疫情的发酵,加速推动各行各业进入数据时代的步伐.美业,一个通过自身技术.产品让用户变美的行业,在AI大数据的加持下表现尤为突出. 对于美妆护肤企业来说,一边是进入存量市场,一边是疫后的复苏期,一边 ...

  3. Redis-4.X 版本 Redis Cluster集群 (一)

    一 创建redis cluster 集群前提条件: 1 ) 每个redis node 节点采用相同的硬件配置,相同的密码. 2 ) 每个节点必须开启的参数: cluster-enabled yes # ...

  4. MyBatis 查询的时候属性名和字段名不一致的问题

    目录 问题 解决方案:resultMap 问题 当我们数据库中的字段和实体类中的字段不一致的时候,查询会出问题 数据库字段是 pwd id name pwd 1 张三 123456 2 李四 1234 ...

  5. python3 最基本且简单的实现组合设计模式

    组合模式是把一个类别归为一个整体,并且组织多个整体之间的关系,使用通过树形结构来描述所有整体. 一般的编写方式为一个类别对象下添加多个该对象的元素,该对象又为其它对象下的元素.简单来说就是一个学校有一 ...

  6. 【Oracle】查看表空间是否为自动扩展

    查看指定的表空间是否为自动扩展 SQL>   select file_name,autoextensible,increment_by from dba_data_files where tab ...

  7. C/C++内存对齐详解

    1.什么是内存对齐 还是用一个例子带出这个问题,看下面的小程序,理论上,32位系统下,int占4byte,char占一个byte,那么将它们放到一个结构体中应该占4+1=5byte:但是实际上,通过运 ...

  8. xray—学习笔记

    长亭xray扫描器 简介 xray (https://github.com/chaitin/xray) 是从长亭洞鉴核心引擎中提取出的社区版漏洞扫描神器,支持主动.被动多种扫描方式,自备盲打平台.可以 ...

  9. 误删数据库怎么办?mysql 回滚,撤销操作,恢复数据

    刚刚不小心把数据库删掉了,于是想着上网上找找有没有可以恢复数据库的方法,没想到还真有,除了备份以外,还有以下方法. 在mysql有时执行了错误的update或者delete时导致大量数据错误恢复的办法 ...

  10. 1V转3.3V稳压供电的芯片电路图

    1V转3.3V供电是简单的,仅需要一个芯片和三个外围元件即可组成这样的一个1V转3.3V的电路图和升压电路了.可以持续稳定地供电3.3V给模块或者MCU灯电路.让后端工作稳定,同时也能控制电路的功耗. ...