图论常见算法总结——prim,kruskal,dijkstra,floyed,bellman-ford,spfa

一、求最小生成树

题目链接:https://www.luogu.com.cn/problem/P3366

1.prim算法

任意选取一个起点u,设已加入树的结点为V,总结点为T,则每次搜索连接V与T-V的最短边,并使之加入V(即从T-V向V中加入一个新的节点),当T中所有节点访问完成,即为最小生成树。

优先级队列版实现代码:

#include <iostream>
#include <queue>
using namespace std;
#define MK make_pair
const int N = 5003, M = 400050,INF=(1<<30);
int to[M], w[M], nxt[M], tot;//链式前向星
int h[N], dis[N];
bool visit[N];
int n, m;
priority_queue<pair<int, int>> q;
void add(int a, int b, int c) {
	to[++tot] = b;        //链式前向星加边
	w[tot] = c;
	nxt[tot] = h[a];
	h[a] = tot;
}
void prim() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		dis[i] = INF;
	}
	for (int i = 1, a, b, c; i <= m; i++) {
		cin >> a >> b >> c;
		add(a, b, c); add(b, a, c);//无向图加双边
	}
	q.push(MK(0, 1));
	dis[1] = 0;
	pair<int, int> now;
	int d, u;
	while (!q.empty()) {
		now = q.top(); q.pop();
		d = -now.first; u = now.second;   //默认最大堆,所以插入负权值,确保堆顶为最小权值
		if (dis[u]<d) continue;//已更新过最小权值,舍弃
		visit[u] = true;
		for (int i = h[u], v; v = to[i]; i = nxt[i]) {
			if (dis[v] > w[i] && !visit[v]) {
				dis[v] = w[i];            //若枚举的边可使T-V到V的路径变短,更新
				q.push(MK(-dis[v], v));    
			}
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		if (dis[i] == INF) {
			cout << "orz"; return;
		}
		ans += dis[i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值