我在这里就讲两种方法

PrimKruscal


Kruscal

kruscal的本质其实是 排序+并查集 ,是生成树中避圈法的推广

算法原理如下

  • (1)将连通带权图G=<n,m>的各条边按从小到大的次序排列,写成E1,E2,···Em,其中E1的权最小,Em的权最大,m为边数。//这就是排序的原因
  • (2)取权最小的两条边E1,E2,构成边的集合T,即T={E1,E2}。从E3起,按次序逐个将边加进集合T中去,若出现回路则将这条边排除(不加进去),按此法一直进行到Em,最后得到n-1条边的集合T={E1,E2,E3,···En-1},则T就是图G的最小生成树。//并查集

如果不会并查集的同学,可以点进去看看

并查集

其中大家可以看到,我的快速排序并没有写cmp,这是因为我用了重载运算符

可以看一看一大佬写的,简单易懂

CSDN 重载运算符

贴代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
struct edge
{
int to,from,next,v;
bool operator <(const edge &n)const
{
return v<n.v;
}//重载<符号,排序时要用
}e[400000+10];
int head[2300+10],ei=0;
inline int add(int x,int y,int z)
{
ei++;
e[ei].to=y;
e[ei].next=head[x];
e[ei].v=z;
head[x]=ei;
e[ei].from=x;
}//前向星模板,萌新们不知道可以去百度一下
int f[2300+10];//爸爸数组~~~
inline int findf(int x)
{
if(f[x]==0)
{
return x;
}
f[x]=findf(f[x]);
return f[x];
}
inline int uion(int x,int y)
{
x=findf(x);
y=findf(y);
if(x!=y)
{
f[x]=y;
}
}//并查集模板
int ans=0;//答案
/*int cnt=0;*/
inline int kruscal()
{
for(int i=1;i<=m;i++)
{
int fx=findf(e[i].from);
int fy=findf(e[i].to);
if(fx==fy) continue;
ans+=e[i].v;
uion(e[i].from,e[i].to);
/*cnt++;
if(cnt==n-1)
{
break;
}
这就是这道题与P3366的模板的第一个区别
这道题强调了要重复的
所以不需要判断
*/
}
}//kruscal模板
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
x++;
y++;//这是第二个区别,楼上已经解释的很清楚了,由于题上说了,ai=0表示mzc,会有三个点WA
add(x,y,z);
}
sort(e+1,e+m+1);//STL库的快速排序,kruscal的惯例
kruscal();
printf("%d",ans);//输出~~~~
return 0;
}

好,现在我们即将进入prim


Prim

prim也称 逐步短接法 (是不是有点土),本质是搜索,其实有点像最短路问题中的Dijkstra算法,先给出短接的定义:

定义:

设Vi和Vj是无向图G=<V,E>中的任意两顶点,将Vi,Vj合并成一个顶点,记做V',称V'为超点,使得与Vi,Vj关联的边均与V'关联。这种做法称为Vi,Vj的短接

Prim的算法原理如下:

  • (1)设e是G中非环带权最小的边(若带权最小的边不唯一,就任选一个作为e),将e的两端点Vi,Vj短接得起点V'。删除边e(相当于将e作为生成树的树枝)后,所得的图G'中若含有环就删除掉(相当于形成生成树的弦)。//搜索的过程
  • (2)对G'重复(1),直到最后整个图变成一个起点为止。这时共进行n-1次短接,得n-1个树枝,m-n+1条弦。

可以看到,在我的程序中出现了堆排序优化,不懂的同学请戳这里

堆排序

当然,除了我这种堆排序的写法,还有Priority_queue即优先队列的写法,但我测试过,我这种写法,至少快1/3。若果还是不懂我这种写法的,戳这里

优先队列

贴代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
int ans=0;
struct edge
{
int next,to,v;
}e[400000+10<<1];
int head[2300+10],ei=0;
int add(int x,int y,int v)
{
ei++;
e[ei].to=y;
e[ei].next=head[x];
head[x]=ei;
e[ei].v=v;
}//与上一方法相同
struct node
{
int id,v;
bool operator<(const node &n)const
{
return v>n.v;
}//堆排序时要用,重载<,使得进去的数上小下大
};
node heap[400000+10];//堆
int heaplen = 0; //堆的长度
int pushHeap(int x,int v)
{
heap[heaplen].id = x;
heap[heaplen].v = v;
heaplen++;
push_heap(heap,heap+heaplen);
}//入堆
node popHeap()
{
pop_heap(heap,heap+heaplen);
heaplen--;
return heap[heaplen];
}//出堆
int used[400000+10];//堆栈优化,不然要炸
/*int blcnt=0;*/
int prim()
{
pushHeap(1,0);//先把第一个数和其边权(因为没有下一节点,所以是0) 入堆
while(heaplen)//搜索
{
node f1=popHeap(); //出堆并记录顶上的一个数
if(used[f1.id]==1)
{
continue;
}
used[f1.id]=1;
ans+=f1.v;
/*blcnt++;
if(blcnt==n)
{
printf("%d",ans);
}
和上一个方法一样,不需要判断
*/
for(int i=head[f1.id];i;i=e[i].next)//遍历前向星
{
if(used[e[i].to]==0)
{
pushHeap(e[i].to,e[i].v);//入堆
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
x++;
y++;//同上一种方法
add(x,y,z);
add(y,x,z);//双向存储
}
prim();
printf("%d",ans);//输出~~~
return 0;
}

现在说一下这道题容易出错的地方

  1. 这道题强调了要重复的,所以不需要判断cnt==n-1时,将循环停掉。可以看一看我的错误WA

  2. 由于题上说了,ai=0表示mzc,所以标记值和此处重复。

    我的错误WA+RE。如某大佬:

但在写的时候遇到了一点bug,以为数据中的人是 有编号为0的 ,那么我的并查集的写法就会 因为标记的值和0重复了而被卡掉 ,所以就 人为的将每一个编号放大1 ,然后就A了


如果有小伙伴们不懂链式前向星这种存储方式,戳这里

链式前向星

如果大家觉得我讲的你不懂,请参考下面这位大佬的讲解

Prim和Kruscal


最后推荐几道题:

P1119 灾后重建

P3366 【模板】最小生成树

P1195 口袋的天空


最后,衷心祝愿每一个人都能实现自己的梦想,得到省一

理想的梦,
希望的梦,
希望中,
那理想的梦,
像一幅春天的画卷,
在不懈的期盼中,
悄悄的在梦中闪现。 阻挠,
蔑视,
肆意的嘲笑,
还有那狂妄的刁难,
这一刻,
像这冬日的寒风,
飘到了九霄云外。 理想的梦,
生命中的梦,
生命中,
那激情的火焰,
像冬日燃烧的枯草,
在寒风中熊熊的燃烧。 燃烧中,
我恍然站在了那泰山之巅,
遥望起了那远方的苍海云天。 遥望中,
东方升起了一轮红日,
这红日是如此的绚丽,
如此的闪耀。 闪耀中,
一阵细雨,
突然飘来。 雨中的我,
恍然如梦。

探秘最小生成树&&洛谷P2126题解的更多相关文章

  1. [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码

    [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码 更坏的阅读体验 定义 对于给定的一个网络,有向图中每个的边权表示可以通过的最大流量.假设出发点S水流无限大,求水流到终点T后的最大流量. 起 ...

  2. 最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网

    嗯... 理解生成树的概念: 在一幅图中将所有n个点连接起来的n-1条边所形成的树. 最小生成树: 边权之和最小的生成树. 最小瓶颈生成树: 对于带权图,最大权值最小的生成树. 如何操作? 1.Pri ...

  3. 洛谷P5759题解

    本文摘自本人洛谷博客,原文章地址:https://www.luogu.com.cn/blog/cjtb666anran/solution-p5759 \[这道题重在理解题意 \] 选手编号依次为: \ ...

  4. 关于三目运算符与if语句的效率与洛谷P2704题解

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

  5. c++并查集配合STL MAP的实现(洛谷P2814题解)

    不会并查集的话请将此文与我以前写的并查集一同食用. 原题来自洛谷 原题 文字稿在此: 题目背景 现代的人对于本家族血统越来越感兴趣. 题目描述 给出充足的父子关系,请你编写程序找到某个人的最早的祖先. ...

  6. 洛谷P2607题解

    想要深入学习树形DP,请点击我的博客. 本题的DP模型同 P1352 没有上司的舞会.本题的难点在于如何把基环树DP转化为普通的树上DP. 考虑断边和换根.先找到其中的一个环,在上面随意取两个点, 断 ...

  7. 洛谷——P2126 Mzc家中的男家丁

    P2126 Mzc家中的男家丁 题目背景 mzc与djn的…还没有众人皆知,所以我们要来宣传一下. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁,现在mzc要将她们全都聚集起来(干什么就不知道 ...

  8. 【洛谷】题解 P1056 【排座椅】

    题目链接 因为题目说输入保证会交头接耳的同学前后相邻或者左右相邻,所以一对同学要分开有且只有一条唯一的通道才能把他们分开. 于是可以吧这条通道累加到一个数组里面.应为题目要求纵列的通道和横列的通道条数 ...

  9. 洛谷P3572题解

    这道题实在是一道 毒瘤 题,太坑爹了.那个写 \(deque\) 的题解亲测只有80分,原因 不言而明 ,这道题居然 丧心病狂 到 卡STL . 好了,不吐槽了,进入正题 题目分析: 这是一道十分 简 ...

随机推荐

  1. Docker搭建MySQL主从集群,基于GTID

    写在前边 搭建MySQL读写分离主从集群,这里未使用binlog方式,使用的是GTID方式 源码见我的Github https://github.com/hellxz/mysql-cluster-do ...

  2. Confluence迁移

    本次操作系统版本Centos7.3,Confluence版本5.9.9. 一.数据迁移 1.在旧Confluence上打包 “confluence和confluence-data”整个目录,默认安装的 ...

  3. springboot使用RabbitMQ实现延时任务

    延时队列顾名思义,即放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费.那么,为什么需要延迟消费呢?我们来看以下的场景 订单业务: 在电商/点餐中,都有下单后 30 分钟内没有付款 ...

  4. Facebook也炒币吗?Libra币是什么?

    Facebook 在上周发布了加密数字货币,称为 Libra币. 太火爆了,很多人都在关注和讨论,包括一些科技大佬们都很积极的讨论(当然,这里指的是真正的科技大佬,比如 马化腾.王兴等,而不是指哪些割 ...

  5. HDU 5510:Bazinga(暴力KMP)

    http://acm.hdu.edu.cn/showproblem.php?pid=5510 Bazinga Problem Description   Ladies and gentlemen, p ...

  6. 从零开始实现放置游戏(十)——实现战斗挂机(1)hessian服务端搭建

    前面实现RMS系统时,我们让其直接访问底层数据库.后面我们在idlewow-game模块实现游戏逻辑时,将不再直接访问底层数据,而是通过hessian服务暴露接口给表现层. 本章,我们先把hessia ...

  7. c++指针经典题目分析

    首先看一下题目,下列程序会在那一行崩溃,程序如下: #include<iostream> using namespace std; struct S{ int i; int *p; }; ...

  8. linux_硬链接和软链接区别

    硬链接有点类似于复制的概念.    ln 源文件 目的文件    ln不加-s,则默认是硬链接.例如,ln script script-hard,ls命令显示,script*显示硬链接有两个.我任意删 ...

  9. 我的it博客开张啦

    今天怀着激动地心情,在这里写下第一篇开博.之前也在新浪.网易等申请过博客,并且将新浪博客作为我的个人技术博客,当有一天看到cnblog时,觉得这里的博客以一本精美的书的批复呈现时,顿觉得很有...咋说 ...

  10. 简易数据分析 06 | 如何导入别人已经写好的 Web Scraper 爬虫

    这是简易数据分析系列的第 6 篇文章. 上两期我们学习了如何通过 Web Scraper 批量抓取豆瓣电影 TOP250 的数据,内容都太干了,今天我们说些轻松的,讲讲 Web Scraper 如何导 ...