最短路---C++---SPFA

6 篇文章 0 订阅
5 篇文章 0 订阅

问题描述

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

输入
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。输入保证至少存在1条商店到赛场的路线。 当输入为两个0时,输入结束。

输出
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间。
输入例子 1

3 3
1 2 1
2 3 1
1 3 3
3 3
1 2 2
2 3 1
1 3 1
0 0

输出例子

2
1

实现代码

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>

using namespace std;

const int Inf = 0x3f3f3f3f;
const int maxn = 100 + 5;
const int maxm = 10000 + 5;
int head[maxn], inq[maxn], dis[maxn];
int cnt = 0;

struct Edge {
	int next, to, time;
	Edge() {}
	Edge(int next, int to, int time) : next(next), to(to), time(time) {}
}edges[maxm];

void Link(int from, int to, int time) { 
	edges[++cnt] = Edge(head[from], to, time);
	head[from] = cnt;
}

void spfa(int s, int e) {
	memset(dis, Inf, sizeof(dis));
	memset(inq, 0, sizeof(inq));
	queue<int> q;
	q.push(s);
	dis[s] = 0, inq[s] = 1;
	while (q.size()) { 
		int now = q.front(); q.pop();
		inq[now] = 0;
		for (int i = head[now]; i; i = edges[i].next) {
			int to = edges[i].to, time = edges[i].time;
			if (dis[to] > dis[now] + time) {
				dis[to] = dis[now] + time;
				if (!inq[to]) {
					q.push(to);
					inq[to] = 1;
				}
			}
		}
	}
	cout<< dis[e] <<endl;
}

int main() {
	int n, m, a, b, c;
	while (cin >> n >> m)
	{
		if (!n && !m) break;
		cnt = 0;
		memset(head, 0, sizeof(head));
		while (m--)
		{
			cin >> a >> b >> c;
			Link(a, b, c);
			Link(b, a, c);
		}
		spfa(1, n);
	}
	return 0;
}

在学校的垃圾OJ运行错误,在杭电AC了,emm,不愧是高建。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是A*双向搜索的C++代码: ```c++ #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; const int M = 2e6 + 5; struct Edge { int to, w, nxt; } e[M << 1]; int head[N], tot; int n, m, s, t; int vis[N], dis[N], g[N], f[N]; int que[N], top, tail; inline void add(int u, int v, int w) { e[++tot].to = v; e[tot].w = w; e[tot].nxt = head[u]; head[u] = tot; } inline void spfa(int s, int *dis, int *h) { top = 0, tail = 1; que[1] = s; memset(dis, 0x3f, sizeof(dis)); dis[s] = 0, h[s] = 0; while (top < tail) { int u = que[++top]; vis[u] = 0; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (dis[v] > dis[u] + e[i].w) { dis[v] = dis[u] + e[i].w; h[v] = h[u] + 1; if (!vis[v]) { vis[v] = 1; que[++tail] = v; } } } } } int astar(int s, int t) { memset(vis, 0, sizeof(vis)); memset(g, 0x3f, sizeof(g)); memset(f, 0x3f, sizeof(f)); g[s] = 0, f[s] = h[s]; int ans = INT_MAX; top = tail = 0; que[++tail] = s; while (top < tail) { int u = que[++top]; if (g[u] + h[u] >= ans) continue; if (u == t) { ans = min(ans, g[u] + h[u]); continue; } vis[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to, w = e[i].w; if (vis[v]) continue; if (g[v] > g[u] + w) { g[v] = g[u] + w; f[v] = g[v] + h[v]; que[++tail] = v; } } sort(que + top + 1, que + tail + 1, [](int u, int v) { return f[u] > f[v]; }); } return ans; } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for (int i = 1; i <= m; ++i) { int u, v, w; scanf("%d%d%d", &u, &v, &w); add(u, v, w); add(v, u, w); } scanf("%d", &h[t]); spfa(s, dis, g); int ans = astar(s, t); memset(vis, 0, sizeof(vis)); spfa(t, dis, g); for (int i = 1; i <= n; ++i) { for (int j = head[i]; j; j = e[j].nxt) { int u = i, v = e[j].to, w = e[j].w; if (g[u] + w + h[v] == ans) { e[j].w = 0; add(v, u, 0); } } } memset(vis, 0, sizeof(vis)); printf("%d\n", astar(s, t)); return 0; } ``` 其中,`add(u, v, w)` 函数用于向邻接表中添加一条从节点 `u` 到节点 `v`,权值为 `w` 的边。 `spfa(s, dis, h)` 函数用于从节点 `s` 开始进行一次SPFA算法,最终将每个节点到节点 `s` 的最短距离存储在 `dis` 数组中,将每个节点到目标节点 `t` 的估价函数值存储在 `h` 数组中。 `astar(s, t)` 函数用于进行一次A*搜索,返回从节点 `s` 到节点 `t` 的最短路长度。在搜索过程中,我们使用 `g` 数组存储从节点 `s` 到当前节点的距离,使用 `h` 数组存储当前节点到目标节点 `t` 的估价函数值,使用 `f` 数组存储当前节点的估价函数值。我们使用一个优先队列来维护搜索顺序。 在主函数中,我们首先使用 `spfa(s, dis, g)` 计算出正向图的最短路长度和每个节点到目标节点的估价函数值,然后使用 `astar(s, t)` 进行双向A*搜索,将每条满足条件的边的权值设置为0,再将这些边添加到反向图中,最后使用 `astar(s, t)` 计算出反向图的最短路长度,即为双向A*搜索的结果。 需要注意的是,在进行反向图的SPFA算法时,需要将 `dis` 数组和 `g` 数组重新初始化为正无穷值,因为这些数组在正向图的SPFA算法和A*搜索中被修改过了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值