每日算法(7):求解自行车慢速问题(贝尔曼—福特法)

题目:一个美丽的小岛上有许多景点,景点之间有一条或者多条道路。现在进行自行车慢速比赛(最慢的选手获得冠军),工作人员在道路上标出自行车的单向行驶方向,所有比赛线路不会出现环,选手不能在中途的任何地方停下来,否则犯规,退出比赛。首先给定一行两个整数N和M,N为岛上的景点数(景点编号为0~N-1,N≤100),接下来的M行,每行为a、b、l,表示景点a和景点b之间的单向路径长度为L(L为整数)。最后一行为s和t,表示比赛的起点s和终点t。所有选手水平高超,都能够以自行车的最低速度行驶,并且所有自行车的最低速度相同。问冠军所走的路径长度是多少?假设只有一组测试数据。

输入:

7 10

1 2 5

1 5 6

1 6 8

2 3 7

2 6 4

3 6 5

4 5 9

4 7 5

5 6 3

6 7 2

1 5

输出:

6

思路:

典型最短路径算法,用于计算一个节点到其他节点的最短路径。这里可以考虑图算法—贝尔曼福特算法。

基本原理:逐遍的对图中每一个边去迭代计算起始点到其余各点的最短路径,执行N-1遍,最终得到起始点到其余各点的最短路径。(N为连通图结点数)

特点:贝尔曼福特算法是直接对所有边进行N-1遍松弛操作。

贝尔曼福特算法边的权值可以为负数,并可检测负权回路。

名词解释:

1. 松弛操作:不断更新最短路径和前驱结点的操作。

2. 负权回路:绕一圈绕回来发现到自己的距离从0变成了负数,到各结点的距离无限制的降低,停不下来。参考:算法系列——贝尔曼福特算法(Bellman-Ford)_lzh1366的博客-CSDN博客

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define INF 0x3f3f3f3f			//定义∞
#define MAXV 101
int A[MAXV][MAXV];			//邻接矩阵
int n, m;
int s, t;
int dist[MAXV];
void BellmanFord(int v)			//贝尔曼-福特算法
{
	int i, k, u;
	for (i = 0; i < n; i++)
		dist[i] = A[v][i];		//对dist0[i]初始化
	for (k = 1; k < n; k++)			//从dist0[u]递推出dist2[u], …,distn-1[u]循环n-2次
	{
		for (u = 0; u < n; u++)		//修改所有非顶点v的dist[]值
		{
			if (u != v)
			{
				for (i = 0; i < n; i++)
				{
					if (A[i][u]<INF && dist[u]>dist[i] + A[i][u])
						dist[u] = dist[i] + A[i][u];
				}
			}
		}
	}
}
int main()
{
	int i, j;
	int a, b, l;
	scanf("%d%d", &n, &m);		//输入n、m
	for (i = 0; i < n; i++)				//初始化邻接矩阵
		for (j = 0; j < n; j++)
			if (i == j)
				A[i][j] = 0;
			else
				A[i][j] = INF;
	for (i = 0; i < m; i++)			//输入边
	{
		scanf("%d%d%d", &a, &b, &l);
		A[a][b] = -l;
	}
	scanf("%d%d", &s, &t);		//输入s和t
	BellmanFord(s);				//采用BellmanFord算法求s出发的最短路径
	printf("%d\n", -dist[t]);		//输出结果
	return 1;
}

 结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值