【图论】【最短路】【SPFA】廉价最短路径

本文深入探讨了SPFA算法在寻找图中廉价最短路径的应用,通过具体实例详细解析了算法的实现过程,包括如何处理顶点和边,以及如何通过调整判断条件来找到既短又经济的路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

图是由一组顶点和一组边组成的。一条边连接两个顶点。例如,图1表示了一个有4个顶点V、5条边的图。图中,每条边e是有方向的,方向从起点到终点,并且每条边都有价值。用整数0,1,…,m-1可以表示一个有m个顶点的图。

一条路径连接了一个点Vi和另一个点Vj,其方向与经过的一系列边的方向一致。路径的长度是途经边的条数,路径的费用是边价值的总和。对于一个给定的图,你的任务是在所有最短路径中,找出需要最少费用的连接V0和V1的路径。一个需要最少费用的最短路径称之为廉价最短路径。
让我们重新考虑图1,从0到1的最短路径是只含一条边的路径0→1,费用是10。当然,还有更便宜的路:0→2→1和 0→3→1,但是它们比第一条路径长(有2条边)。所以,0→1是廉价最短路径。
看一下另一个例子,图2,它有2条最短路径,其长度是2,路径0→3→1(费用=4)比路径0→2→1(费用=5)花费少。还用另一条路径0→2→3→1(费用=3),虽然便宜但是很长。所以,廉价最短路径是0→3→1。

输入

输入文件第一行有两个整数m和n,用一个空格隔开,其中,m是顶点数,而n是边数。接下来的n行给出所有的边及其价值,每行有3个整数(相邻两个整数间有一个空格),表示起点,终点和边的价值。顶点最多有100个,编号在0到99之间。边最多有1000条,其价值在0到2^15-1之间。

输出

输出文件仅有一行包含一个整数,即V0→V1的廉价最短路径的费用。当出现有多个廉价最短路径的情况时,它们的费用是一样的。

输入样例
4 5
0 2 2
0 3 2
0 1 10
2 1 2
3 1 2
输出样例
10

思路

直接用SPFA
然后改一下判断

#include<Algorithm>
#include<Iostream>
#include<Cstring>
#include<Cstdio>
#include<Cmath>
#include<Queue>
using namespace std;
struct whw
{
	int w,h,t;
}wh[200025];
int Ans[2][225],B[225],h[225];
int n,m,x,y,z,t;
void hw(int x,int y,int z)
{wh[++t]=(whw){y,h[x],z};h[x]=t;}
void SPFA()
{
	memset(Ans,0x3f,sizeof(Ans));
	queue<int>A;
	A.push(0);
	B[0]=0;
	Ans[0][0]=Ans[1][0]=0;
	while(A.size())
	{
		x=A.front(); 
		A.pop();
		for(int i=h[x],y=wh[h[x]].w;i;i=wh[i].h,y=wh[i].w)
			if(Ans[0][x]+1<Ans[0][y]//如果走的步数更少
			|| Ans[0][y]==1061109567//如果没走过
			|| (Ans[0][x]+1==Ans[0][y]//如果相同步数
			&& Ans[1][x]+wh[i].t<Ans[1][y]))//且价值更小
			{
				Ans[1][y]=Ans[1][x]+wh[i].t;
				Ans[0][y]=Ans[0][x]+1;
				if(!B[y])
				{
					B[y]=1;
					A.push(y);
				}
			}
		B[x]=0;
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d%d",&x,&y,&z);
		hw(x,y,z);
	}
	SPFA();
	printf("%d",Ans[1][1]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值