最小生成树与瓶颈生成树 -- HL集训复习day3

概念:
生成树:
无向连通图G 的一个子图如果是包含G 的所有顶点的树,那么就称这个子图为G 的生成树。(树的话简而言之就是有n-1条边n为点数,也就是每两点只有一条边相连)
我们称生成树各边权值和为该树的权。对于无向连通图来说,权最小的生成树被成为最小生成树
对树不了解的话点这里(百度百科)

最小生成树

Kruskal算法

Kruskal 算法是能够在O(mlogm) 的时间内得到一个最小生成树的算法。
它主要是基于贪心的思想:
① 将边按照边权从小到大排序,并建立一个没有边的图T。
② 选出一条没有被选过的边权最小的边。
③ 如果这条边两个顶点在T 中所在的连通块不相同,那么将它加入图T。
④ 重复②和③直到图T 连通为止。
由于只需要维护连通性,可以不需要真正建立图T,可以用并查集来维护

#include<bits/stdc++.h>

#define MAXN 100010
#define N 500
#define INF 0x3f3f3f3f

using namespace std;

struct node{
	int x,y,ne,z;
}e[MAXN];

int fa[MAXN];
int n,m,ans;

bool memcy(node a, node b){
	return a.z < b.z;
}

int get(int x){
	return fa[x] == x ? x : fa[x] = get(fa[x]);
}

void kruscal(){
	sort(e + 1, e + 1 + m, memcy);
	for(int i = 1; i <= n; ++i) fa[i] = i;
	for(int i = 1; i <= m; ++i){
		int x = get(e[i].x), y = get(e[i].y);
		if(x != y){
			fa[x] = y;
			ans += e[i].z;
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= m; ++i){
		int x,y,z;
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
	}
	kruscal();
	printf("%d\n",ans);
	return 0;
}

prim算法

#include<bits/stdc++.h>

#define MAXN 100010
#define N 3010
#define INF 0x3f3f3f3f

using namespace std;

int a[N][N],d[MAXN],v[MAXN];
int n,m;
int ans = 0;

void prim(){
	memset(d,63,sizeof(d));
	memset(v,false,sizeof(v));
	d[1] = 0;
	for(int i = 1; i < n; ++i){
		int x = 0;
		for(int j = 1; j <= n; ++j)
			if(!v[j] && (x == 0 || d[j] < d[x])) x = j;
		v[x] = true;
		for(int j = 1; j <= n; ++j)
			if(!v[j]) d[j] = min(d[j],a[x][j]);
	}
}
int main()
{
	memset(a,63,sizeof(a));
	cin>>n;
	m = n * n;
	forint i = 1; i <= n; ++i) a[i][i] = 0;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j){
			int w;
			scanf("%d",&w);
			a[j][i] = a[i][j] = min(a[i][j],w);
		}
	prim();
	for(int i = 2; i <= n; ++i)
		ans += d[i];
	printf("%d\n",ans);
	return 0;
}

瓶颈生成树

无向图G的一颗瓶颈生成树是这样的一颗生成树T:它最大的边权
值在G的所有生成树中是最小的。瓶颈生成树的值为T中最大权值边的
权。

一个结论:无向图的最小生成树一定是瓶颈生成树,但瓶颈生成树
不一定是最小生成树。

例题

网络布线

{
☆网络布线
描述 Description
农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。每两个农场间的距离不会超过100000
输入格式 Input Format
第一行: 农场的个数,N(3<=N<=100)。
第二行…结尾: 后来的行包含了一个N*N的矩阵,表示每个农场之间的距离。当然,对角线将会是0,因为不会有线路从第i个农场到它本身。
输出格式 Output Format
只有一个输出,其中包含连接到每个农场的光纤的最小长度。
样例输入 Sample Input

4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0

样例输出 Sample Output

28
时间限制 Time Limitation
1s


如果仔细看过prim的话挺裸的。上面prim代码就是这道题答案。
并且还不用把对角线赋零和双向建边。(上面我做了这俩事)
模板题
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIGBIGPPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值