P3366 【模板】最小生成树

    • 2.4K通过
    • 6.3K提交
  • 题目提供者HansBug
  • 标签 云端↑ 生成树
  • 难度 普及-
  • 时空限制 1s / 128MB

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出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

样例解释:

所以最小生成树的总边权为2+2+3=7

思路:

  首先这道题是求最小生成树的模板,求最小生成树的办法有2种:

    1)prim

    2)kruskal

坑点:

  1)记住要判断什么时候输出“orz”

  2)在使用prim算法的时候,我使用的是邻接矩阵,不清楚你们用的什么,在邻接矩阵进行输入的时候,一定要进行判断一下在进行赋值!!

  数据中有重边!!数据中有重边!!数据中有重边!!需要选取较小的一条,即算法中已经被选出来的节点不用再次进行赋值。

  调了2天qwq,血的教训qwq(还有这种操作吗???orz)

上代码:

1)prim

  在网页上找了不少题解后,突然发现,还是kruskal比较好理解。。。

  写prim的有各式各样的2333

我就写了一种嘻嘻

#include <iostream>
#include <cstdio>
#define Maxx 0x7fffffff using namespace std; const int M = ;
int n,m; //n=顶点的个数,m=边的个数
int edge[M][M]={ /*输入的邻接矩阵*/ };
int lowcost[M]; //记录Vnew中每个点到V中邻接点的最短边
bool visited[M]; //标记某点是否加入Vnew
int pre[M]; //记录V中与Vnew最邻近的点 void prim(int start)
{
int sumweight=,i,j,k=;
visited[start]=true;
for(i=;i<=n;i++)
{
lowcost[i]=edge[start][i];
pre[i]=start;
}
int minn=Maxx; //最小权值
int v=-; //所对应的下标
for(i=;i<n;i++) //进行n-1次,因为此时已经知道当前start点到另一点距离最短
{
minn=Maxx;
for(j=;j<=n;j++)
{
if(visited[j]==false && lowcost[j]<minn) //在Vnew之外寻找最短路径
{
minn=lowcost[j]; //最短路径
v=j;
}
}
// printf("%d %d %d\n",pre[v],v,lowcost[v]);
if(v==-)
{
cout<<"orz"<<endl;
return;
}
visited[v]=true; //将v加Vnew中
sumweight+=lowcost[v]; //计算路径长度之和
for(j=;j<=n;j++)
{
if(visited[j]==false && edge[v][j]<lowcost[j])
{
lowcost[j]=edge[v][j]; //此时v点加入Vnew 需要更新lowcost
pre[j]=v;
}
}
}
// printf("the minmum weight is %d",sumweight); //进行输出
printf("%d",sumweight);
} int main()
{
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
{
// lowcost[i]=Maxx;
for(int j=; j<=n; j++)
edge[i][j]=Maxx; //初始化图
}
int x,y,w,s,Max=Maxx;
for(int k=; k<=m; k++)
{
cin>>x>>y>>w;
if(w<edge[x][y])
edge[x][y]=edge[y][x]=w; //构建图
if(w<Max)
{
Max=w;
s=x; //寻找最初最"实惠"的点
}
}
prim(s); //进行求解最小生成树
return ;
}

2)kruskal

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std; const int N = ;
const int M = ;
int n,m,ans;
int dad[N]; struct A {
int u,v,w;
bool operator < (const A &qwq)const
{
return w < qwq.w;
}
}t[M]; int getdad(int x)
{ return dad[x] == x ? x : dad[x] = getdad( dad[x] ); } void kruskal()
{
sort(t+,t++m);
for(int i=;i<=m;i++)
{
int f1=getdad(t[i].u),f2=getdad(t[i].v);
if(f1!=f2)
{
dad[f1]=f2;
ans+=t[i].w;
}
}
int tmp=getdad();
for(int i=;i<=n;i++)
{
if(getdad(i)!=tmp)
{
printf("orz");
return;
}
}
printf("%d\n",ans);
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].w);
for(int i=;i<=n;i++)
dad[i]=i;
kruskal();
return ;
}

luoguP3366 【模板】最小生成树 x的更多相关文章

  1. luoguP3366 [模板] 最小生成树

    题目链接:https://www.luogu.org/problemnew/show/P3366 思路: 求最小生成树的模板题,求MST有两种算法——Prim.Kruskal. 两者区别:Prim在稠 ...

  2. 模板<最小生成树>

    转载 最小生成树浅谈 这里介绍最小生成树的两种方法:Prim和Kruskal. 两者区别:Prim在稠密图中比Kruskal优,在稀疏图中比Kruskal劣.Prim是以更新过的节点的连边找最小值,K ...

  3. [洛谷P3366] [模板] 最小生成树

    存个模板,顺便复习一下kruskal和prim. 题目传送门 kruskal 稀疏图上表现更优. 设点数为n,边数为m. 复杂度:O(mlogm). 先对所有边按照边权排序,初始化并查集的信息. 然后 ...

  4. P3366 (模板)最小生成树

    2019-01-30 最小生成树基本算法 定义: 给定一个边带权的无向图G=(V,E),n=|V|,m=|E|,由V中全部n个定点和E中n-1条边构成的无向连通子图被称为G的一颗生成树. 边的权值之和 ...

  5. 模板——最小生成树prim算法&&向前星理解

    通过最小生成树(prim)和最短路径优化引出的向前星存图,时至今日才彻底明白了.. head[i]存储的是父节点为i引出的最后一条边的编号, next负责把head[i]也就是i作为父节点的所有边连接 ...

  6. 模板——最小生成树kruskal算法+并查集数据结构

    并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...

  7. 【洛谷 p3366】模板-最小生成树(图论)

    题目:给出一个无向图,求出最小生成树,如果该图不连通,则输出orz. 解法:Kruskal求MST. 1 #include<cstdio> 2 #include<cstdlib> ...

  8. 洛谷P3366 【模板】最小生成树

    P3366 [模板]最小生成树 319通过 791提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 里面没有要输出orz的测试点 如果你用Prim写了半天都是W- 题目 ...

  9. POJ 2031 Building a Space Station 最小生成树模板

    题目大意:在三维坐标中给出n个细胞的x,y,z坐标和半径r.如果两个点相交或相切则不用修路,否则修一条路连接两个细胞的表面,求最小生成树. 题目思路:最小生成树树模板过了,没啥说的 #include& ...

随机推荐

  1. java字节和字符的区别

    字节: 1.bit=1  二进制数据0或1 2.byte=8bit  1个字节等于8位 存储空间的基本计量单位 3.一个英文字母=1byte=8bit 1个英文字母是1个字节,也就是8位 4.一个汉字 ...

  2. CSS一些常用样式

    限制行数溢出省略号 display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: ; overflow: hidden ...

  3. 生成 excel 插件 Epplus

    最近做 .net core 项目 发现一个新的 生成excel 的插件 . 以前值用 aspose 或者 npio. 简介:Epplus是一个使用Open Office XML(Xlsx)文件格式,能 ...

  4. Redis 简单使用 and 连接池(python)

    Redis 简介 NoSQL(not only sql):非关系型数据库 支持 key-value,  list,  set,  zset,  hash 等数据结构的存储:支持主从数据备份,集群:支持 ...

  5. 如何判断是否是ssd硬盘?win10查看固态硬盘的方法

    转自:http://www.w10zj.com/Win10xy/Win10yh_7732.html 如何判断是否是ssd硬盘?在win10操作系统中我们该如何查看当前主机中安装的是固态硬盘还是机械硬盘 ...

  6. 如何在阿里云上运行SAP UI5应用

    本来Jerry觉得这个知识点太简单了完全不值得写成微信公众号文章,但转念一想,可能网络上有一些刚刚初学UI5的朋友们可能会问到,所以还是写了. 今天一个成都同事问我这个问题,因为SAP WebIDE可 ...

  7. iframe内嵌页面——跨域通讯

      <template> <div class="act-form"> <iframe :src="src" ref=" ...

  8. SuperMemo method

    原文:https://www.supermemo.com/en/archives1990-2015/english/ol/sm2 别人的研究:http://wdxtub.lofter.com/post ...

  9. SPFA找负环(DFS) luogu3385

    SPFA找负环的基本思路就是如果一个点被访问两次说明成环,如果第二次访问时所用路径比第一次短说明可以通过一直跑这个圈将权值减为负无穷,存在负环 有bfs和dfs两种写法,看了一些博客,在bfs和dfs ...

  10. LVM——基本概念

    介绍 LVM(Logical Volume Management)是一种存储设备管理技术,它赋予用户权力,汇集和抽象物理存储设备,从而实现更轻松,更灵活的管理. 利用device mapper这个Li ...