C++算法之——最短路径(基础1)@2020版

C++算法之——最短路径(基础1)@2020版

什么是最短路径

百度中的定义:用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

我自己的理解就是枚举得到最近的一个点,再向外进行探索直到目标点

知识的串通

你可以清晰从定义了解到这就是最基础的广度优先搜索一类的题目,一定会找到最优解。

我新学的时候也会与最小生成树这类的最短问题弄混,但他们是有实质上的不同的。请看:

最小生成树是用和最少的边集将一个图连成任意2点可达,并且这个边集的总长度最小。保证整个拓扑图的所有路径之和最小。通常用Prim算法和kruskal算法求解。
对于数据量在一定限度内时,可以选用较为简单的Kruskal算法,下面写一段基础代码:
我用了并查集进行实现


#include <bits/stdc++.h>
using namespace std;
struct Edge {
	int u, v, w;
};
Edge e[200000];
int father[200], n, en, sum, w, tot;
bool cmp(Edge a, Edge b) {
	return a.w < b.w;
}
int find(int x) {
	if (x == father[x])
		return x;
	return father[x] = find(father[x]);
}
int main() {
	cin >> n;
	en = 0;//  Edge Number;
	// 1. 读入边
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			int w;
			cin >> w;
			if (i != j) {
				en ++;
				e[en].u = i;
				e[en].v = j;
				e[en].w = w;
			}
		}
	}
	// 2. 排序边
	sort(e + 1, e + en + 1, cmp);
	// 3. 一条条选边
	sum = 0;
	for (int i = 1; i <= n; ++i) father[i] = i;
	tot = 0;
	for (int i = 1; i <= en; ++i) {
		int u = e[i].u;
		int v = e[i].v;
		int root1 = find(u); // u所在集合的代表元素,根节点
		int root2 = find(v); // v所在集合的代表元素,根节点
		if (root1 != root2) {
			sum += e[i].w;
			father[root1] = root2;
			tot ++;
		}
		if (tot == n - 1) break;
	}
	cout << sum;
	return 0;
}

现在再放prim算法的代码(可用于时间复杂度为O(n2)的问题

#include <bits/stdc++.h>
using namespace std;
int n, sum;
int dis[1000], w[200][200];
bool vis[200];
int main() {
	cin >> n;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			cin >> w[i][j];
	for (int i = 1; i <= n; ++i) vis[i] = false;
	vis[n] = true;
	for (int i = 1; i < n; ++i)
		dis[i] =  w[i][n]; // dis[i]表示的是第i号点走到白色点的最近的一条边长

	for (int i = 1; i < n; ++i) {
		int v = -1;
		for (int j = 1; j <= n; ++j)
			if (vis[j] == false && (v == -1 || dis[v] > dis[j]))
				v = j;
		if (v == -1) break;
		sum += dis[v];
		vis[v] = true;

		for (int j = 1; j <= n; ++j)
			if (vis[j] == false)
				dis[j] = min(dis[j], w[v][j]);
	}
	cout << sum << endl;
	return 0;
}

到这里,你应该能明白和复习一些基础知识了吧

后记

此文章还没结束,在本周内还会进行修改与补充

此主题我会不断进行更新,若有改进的意见,请发邮件至learning.dlq@gmail.com 或 直接评论即可。

谢谢大家的关注

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值