本题模板,最小生成树,洛谷P3366

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

输入输出格式

输入格式:

第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

输出格式:

输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

输入输出样例

输入样例#1:

4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1:

7

说明

时空限制:1000ms,128M

数据规模:

对于20%的数据:N<=5,M<=20

对于40%的数据:N<=50,M<=2500

对于70%的数据:N<=500,M<=10000

对于100%的数据:N<=5000,M<=200000

下面介绍堆优化后的Prim

首先清楚prim的过程:

给出一个适用于这类问题的推论:给定一张无向图G=(V,E)。n=V的大小,m=E的大小。从E中选出k<n-1条边构成G的一个生成森林。若再从剩余的m-k条边选n-1-k条添加到生成森林中,使其成为G的生成树,并且选出的边的权值之和最小,则该生成树一定包含这m-k条边中连接两个森林的不连通节点的最小边

无论是Prim还是Kruskal都是基于这个推论,但Prim略微有一些改动。

Prim算法总是维护最小生成树的一部分。最初,Prim算法仅确定1号节点属于最小生成树。在任意的时刻,设已经确定属于最小生成树的节点集合为T,剩余节点集合为S。Prim算法找到min(x属于S,y属于T){z},即两个端点分别属于集合S,T的权值最小的边,然后把点x从集合S中删除,加入到集合T中去,并把Z累计到答案(最后答案就是最小生成树的边权值和)。

具体来说,可以维护数组d:对于x属于S,则把d[x]表示节点x与集合T中的节点之间权值最小的边的权值。若x属于T,则d[x]就等于x被加入T选出的最小边的权值

用一个数组标记节点是否属于T。每次从未标记的节点中选出d值最小的,把它标记(加入T),同时
扫描所有出边,更新另一个端点的d值。最后得出答案

可用二叉堆将上述的d数组优化,但其实都不如Kruskal方便。因此Prim主要用于稠密图,尤其是完全图的最下生成树的求解

那么所谓的二叉堆优化实际上就是对于每一次拓展的边加入到一个小根堆中,下面笔者的代码实现用的是priority_queue(我懒)

具体实现看代码

注意不仅要判断堆是否为空还要统计已经维护的点的个数,确保还是小于等于n的

#include<bits/stdc++.h>
#define ll long long
using namespace std; const int maxn=2e5+;
const int mxn=5e3+;
struct node
{
int t;int d;
bool operator < (const node &a) const
{
return d>a.d;
}
};
int n,m;
int vis[mxn];
vector <node> e[mxn];
priority_queue <node> q;
inline int read()
{
char ch=getchar();
int s=,f=;
while (!(ch>=''&&ch<='')) {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
ll prim()
{
ll ans=;
int cnt=;
q.push((node){,});
while (!q.empty()&&cnt<=n)
{
node k=q.top();q.pop();
if (vis[k.t]) continue;
vis[k.t]=;
ans+=k.d;
cnt++;
for (int i=;i<e[k.t].size();i++)
if (!vis[e[k.t][i].t]){
q.push((node){e[k.t][i].t,e[k.t][i].d});
}
}
return ans;
}
int main()
{
n=read();m=read();
for (int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
e[x].push_back((node){y,z});e[y].push_back((node){x,z});
}
printf("%lld",prim());
return ;
}

图论之堆优化的Prim的更多相关文章

  1. hiho一下 第二十九周 最小生成树三·堆优化的Prim算法【14年寒假弄了好长时间没搞懂的prim优化:prim算法+堆优化 】

    题目1 : 最小生成树三·堆优化的Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 回到两个星期之前,在成功的使用Kruscal算法解决了问题之后,小Ho产生 ...

  2. hihocoder 1109 堆优化的Prim算法

    题目链接:http://hihocoder.com/problemset/problem/1109 , 最小生成树 + 堆优化(优先队列). 可以用优先队列,也可以自己手动模拟堆,为了练手,我两种都试 ...

  3. hihoCoder#1109 最小生成树三·堆优化的Prim算法

    原题地址 坑了我好久...提交总是WA,找了个AC代码,然后做同步随机数据diff测试,结果发现数据量小的时候,测试几十万组随机数据都没问题,但是数据量大了以后就会不同,思前想后就是不知道算法写得有什 ...

  4. Prim算法堆优化

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> ...

  5. POJ-1287.Network(Kruskal + Prim + Prim堆优化)

    Networking Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19674   Accepted: 10061 Desc ...

  6. 求最小生成树(暴力法,prim,prim的堆优化,kruskal)

    求最小生成树(暴力法,prim,prim的堆优化,kruskal) 5 71 2 22 5 21 3 41 4 73 4 12 3 13 5 6 我们采用的是dfs的回溯暴力,所以对于如下图,只能搜索 ...

  7. 图论——最小生成树prim+邻接表+堆优化

    今天学长对比了最小生成树最快速的求法不管是稠密图还是稀疏图,prim+邻接表+堆优化都能得到一个很不错的速度,所以参考学长的代码打出了下列代码,make_pair还不是很会,大体理解的意思是可以同时绑 ...

  8. dijkstra(最短路)和Prim(最小生成树)下的堆优化

    dijkstra(最短路)和Prim(最小生成树)下的堆优化 最小堆: down(i)[向下调整]:从第k层的点i开始向下操作,第k层的点与第k+1层的点(如果有)进行值大小的判断,如果父节点的值大于 ...

  9. P3366 【模板】最小生成树(堆优化prim)

    堆优化prim #include<cstdio> #include<cstring> #include<queue> using namespace std; st ...

随机推荐

  1. 在Html5中与服务器交互

    转自原文 在Html5中与服务器交互 刚刚涉足职场,上头就要我研究HTML5,内嵌到手机上,这对我来说完全是一个陌生的领域,不过也正好给自己一个机会来学习,最近做到要跟服务器交互这部分,这部分可是卡了 ...

  2. 输入password登录到主界面,录入学生编号,排序后输出

    n 题目:输入password登录到主界面,录入学生编号,排序后输出 n 1.  语言和环境 A.实现语言 C语言 B.环境要求 VC++ 6.0 n 2.  要求 请编写一个C语言程序.将若干学生编 ...

  3. Android自己定义组件系列【4】——自己定义ViewGroup实现双側滑动

    在上一篇文章<Android自己定义组件系列[3]--自己定义ViewGroup实现側滑>中实现了仿Facebook和人人网的側滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布 ...

  4. 使用C++实现学生管理系统

    我在前面的博客中分别使用C语言的动态数组和链表实现了学生成绩管理系统.近期正好在学习C++,于是我便使用C++实现了学生成绩管理系统.算法和前面的C语言的动态数组实现的学生成绩管理系统几乎相同,仅仅是 ...

  5. keras安装及使用

    安装全称参考https://keras-cn.readthedocs.io/en/latest/for_beginners/keras_linux/ 环境中已配置cuda8.0.cudnn5.0,ub ...

  6. bzoj5106: [CodePlus2017]汀博尔(二分答案)

    5106: [CodePlus2017]汀博尔 题目:传送门 题解: 百题纪念!!! 原谅一下第一百题刷了到水题... 直接二分月份然后判断(注意上界大小) 代码: #include<cstdi ...

  7. zzulioj--1780--和尚特烦恼6——炒股(贪心)

    1780: 和尚特烦恼6--炒股 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 154  Solved: 87 SubmitStatusWeb Boa ...

  8. yum 命令讲解

    (一)yum介绍 Yum(全称为 Yellow dogUpdater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定 ...

  9. Bringing up the Avnet MicroZed with Vivado

    Bringing up the Avnet MicroZed with Vivado I recently received the Adam Taylor Edition of Avnet's Zy ...

  10. 我的Java历程_Java对象类型的转换

    向上转型: 可以将子类对象看作是父类对象叫做“向上转型”,由于向上转型是从一个较为具体的类向较为抽象的类的转换,所以它总是安全的. 例如:可以将正方形.长方形叫做是四边形,但是不能说四边形是正方形或长 ...