最短路径算法

赋权图:与每条边 ( v i − v j ) (v_i-v_j) (vivj)相联系的是穿越该弧的值 c i , j c_{i,j} ci,j,一条路径 v 1 v_1 v1, v 2 v_2 v2 v n v_n vn的值为 ∑ i = 0 n − 1 = c i , i + 1 \sum_{i=0}^{n-1}=c_{i,i+1} i=0n1=ci,i+1.叫做赋权路径长,无权路径长只是路径长的边数。

无权最短路径问题

可以使用BFS,由起始边开始搜索,搜索到,其路径就+1,这也就是最短路径。 将尚未访问到的元素标记为INF。
我这里默认起始点为1,以哪里为起始点,就最先让哪个元素入队就可以了。

#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e6;
const int MOD = 100003;
struct Node {
	bool vis=false;//判断是否走过
	int Dist = INFINITY;//最短路
	int path;//上一个结点
};
vector<int> V[MAX];
queue<int> Q;
Node NodeArr[MAX];
int main() {
	int m, n; cin >> m >> n;
	for (int i = 1; i <= n; i++) {
		int x, y; cin >> x >> y;
		V[x].push_back(y);
		V[y].push_back(x);
	}
	for (int i = 1; i <= m; i++) {
		NodeArr[i].vis = false;
		NodeArr[i].Dist = INFINITY;
	}
	Q.push(1); NodeArr[1].Dist = 0; NodeArr[1].vis = true;
	while (!Q.empty()) {
		int x = Q.front(); Q.pop();
		for (int i = 0; i < V[x].size(); i++) {
			if (NodeArr[V[x][i]].vis==false) {
				NodeArr[V[x][i]].vis = true;
				NodeArr[V[x][i]].Dist = NodeArr[x].Dist + 1;
				NodeArr[V[x][i]].path = x;
				Q.push(V[x][i]);
			}
		}
	}
	for (int i = 1; i <= m; i++)
		cout << NodeArr[i].Dist << endl;
	return 0;
}

无权最短路例题

P1144 最短路计数
该题就是在上述的基础之上,需要增加一个计数功能,用以计数起始点到每一个结点的最短路情况的数量。因为这题要求的是无向图,所以需要反过来push_back一次, c n t [ n ] = ( c n t [ n ] + c n t [ x ] ) % m o d cnt[n]=(cnt[n]+cnt[x]) \%mod cnt[n]=(cnt[n]+cnt[x])%mod,值得一提的是,在要求取模的时候,需要在计算过程中取模,因为计算过程中就可能造成数据过大的情况。

#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e6;
const int MOD = 100003;
vector<int> V[MAX];
queue<int> Q;
bool judge[MAX];
int cnt[MAX],depth[MAX];
int main() {
	int m, n; cin >> m >> n;
	for (int i = 1; i <= n; i++) {
		int x, y; cin >> x >> y;
		V[x].push_back(y);
		V[y].push_back(x);
	}
	for (int i = 1; i <= m; i++) sort(V[i].begin(), V[i].end());
	Q.push(1); judge[1] = 1; cnt[1] = 1;
	while (!Q.empty()) {
		int x = Q.front(); Q.pop();
		for (int i = 0; i < V[x].size(); i++) {
			int n = V[x][i];
			if (!judge[n]) {
				judge[n] = 1;
				depth[n] = depth[x] + 1;
				Q.push(n);
			}
			if(depth[n]==depth[x]+1)
			cnt[n]=(cnt[n]+cnt[x])%MOD;
		}
	}
	for (int i = 1; i <= m; i++)
		cout << cnt[i] << endl;
	return 0;
}

Dijkstra算法

对于上述无权图而言,比较容易解决,但是对于开头所介绍的赋权图而言,问题就要麻烦不少。
Dijkstra算法:Dijkstra算法是通过贪心思想进行的,按阶段进行,在每个阶段,Dijkstra算法选择一个顶点v,他在所有未知顶点中具有最小的 d v d_v dv,同时算法声明从s到v的最短路径是已知的,阶段的其余部分由 d w d_w dw值的更新工作组成。
此算法无法求负权图。
自己用队列写了一个,思路很简单,通过起始点出发,每次结点的dist值都取起始点到达这个点的最小值,思路类似于DP,有错误请指出。

#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e5;
const int INF = 1e9;
struct Node {
	int path;
	int dist=INF;
	bool vis = false;
};
Node NodeArr[MAX];
vector<pair<int,int>> V[MAX];
queue<int> Q;
void Dijkstra(vector<pair<int, int>> V[],int start) {
	Q.push(start); NodeArr[start].dist = 0; NodeArr[start].vis = true;
	while (!Q.empty()) {
		int x = Q.front(); Q.pop();
		for (int i = 0; i < V[x].size(); i++)
		{
			if (NodeArr[V[x][i].first].vis == false) {
				NodeArr[V[x][i].first].vis == true;
				NodeArr[V[x][i].first].path = x;
				int temp = NodeArr[x].dist + V[x][i].second;
				if (NodeArr[V[x][i].first].dist > temp)
					NodeArr[V[x][i].first].dist = temp;
				Q.push(V[x][i].first);
			}
		}
	}
}
int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		int x, y,l; cin >> x >> y >> l;
		V[x].push_back({ y, l });
	}
	Dijkstra(V, 1);
	for (int i = 1; i <= n; i++) {
		cout << NodeArr[i].dist;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值