【最短路】【SPFA】桐人的约会

本文介绍了一种在游戏场景中应用SPFA算法解决最短路径问题的方法,通过实例详细阐述了如何利用SPFA算法找到从起点到终点的最短路径,特别是在存在封边情况下的双向边网络中寻找最短路径的最长路径。

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

题目:

这是一个风和日丽的日子,桐人和诗乃在约会。他们所在的城市共有N个街区,和M条道路,每条道路连接两个不同的街区,并且通过一条道路需要花费一些时间。他们现在处于N号街区,正在享受幸福时光的桐人完全忘记了他的手机被亚丝娜安装了监控装置的事情,此时亚丝娜已经得知了桐人的位置以及他正在和一个妹子约会的事实,十分愤怒,于是从她所在的1号街区火速赶往N号街区。现在这个城市中有一条道路正在维修,不能通行,不过不论是哪条道路处于维修中,均存在一条路径可以从1号街区前往N号街区,而且亚丝娜一定会选取最短路前往N号街区。现在你很好奇,桐人的美好时光最多还能持续多久,即亚丝娜最多要花费多长的时间才能到达N号街区。


输入:

第1行:两个正整数N,M,N表示街区个数,M表示道路数。
第2到M+1行 每行三个整数 u,v,w 表示存在一条连接u和v的道路,通过这条道路花费的时间为w
数据保证没有重边和自环


输出:

一个整数,表示最多花费的时间。


样例输入:

5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10

样例输出:

27

思路:

这道题就是一道最短路(spfa)的变形题,然后考虑封边的情况,还有他是一道双向边,最后看打他的那个点(前驱)找最短路。还有就是他求的是最短路的最长路。


代码:

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int dis[10000],n,m,t,h[10000],ans,qq[10000];
bool le[10000];
struct emm
{
	int w,p,g,gg;
}e[1000000];
void sxb(int u,int v,int w)
{e[++t]=(emm){v,h[u],w,u},h[u]=t;}//双向边函数
void spfa(int ggg)//spfa
{
    memset(dis,0x3f,sizeof(dis));
	memset(le,false,sizeof(le));
	queue<int> z;
	z.push(1);
	le[1]=1;
	dis[1]=0;
	while(z.size())
	{
		int sum=z.front();
		z.pop();
		for(int i=h[sum];i;i=e[i].p)
			if(i==ggg)continue;//封边
			else if(dis[sum]+e[i].g<dis[e[i].w] )//松弛
			{
				dis[e[i].w]=dis[sum]+e[i].g;
				if(!ggg)qq[e[i].w]=i;//记录前驱
				if(!le[e[i].w])
				{
					z.push(e[i].w);
					le[e[i].w]=1;
				}
			}
		le[sum]=0;//出队
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		sxb(u,v,w);sxb(v,u,w);//双向边。
	}
	spfa(0);//先跑一边
	for(int i=n;i!=0;i=e[qq[i]].gg)//用前驱找最短路,0无前驱。
	{
		spfa(qq[i]);//再跑一遍
		if(dis[n]!=dis[0])
		ans=max(ans,dis[n]);//选最优(最短路中的最长路)
	}
	printf("%d",ans);//输出
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值