【SPFA】桐人的约会

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

Input

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

Output

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


思路

枚举最短路上的路径,去掉它们,然后跑SPFA,如此重复。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int f[1001],l[1001],q[1001],n,m,a,b,c,t=0,ans;
bool B[1001];
struct asdf{
	int to,z,next;
} A[1000001];
void SPFA(int x){            //x=去掉的边。x为0就没有代表一条边。
    memset(f,0x7f,sizeof(f));   //初始化。
    memset(B,0,sizeof(B));
	queue<int> Q;
	Q.push(1);
	f[1]=0;
	while(Q.size()){
		int t=Q.front();
		Q.pop();
		B[t]=false;
		for(int i=l[t];i;i=A[i].next)
		  if(f[A[i].to]>f[t]+A[i].z&&i!=x){  //不等于禁用的边
		  	if(x==0) q[A[i].to]=i;   //第一遍SPFA记录路径。
			f[A[i].to]=f[t]+A[i].z;
		  	if(B[A[i].to]==false){
		  		B[A[i].to]=true;
		  		Q.push(A[i].to);
		  	}
		  }
	}
}
int main(){
	memset(A,0x7f,sizeof(A));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i){
		scanf("%d%d%d",&a,&b,&c);
		A[++t].to=b;A[t].z=c;A[t].next=l[a];l[a]=t;
		A[++t].to=a;A[t].z=c;A[t].next=l[b];l[b]=t;
	}
	SPFA(0);       //先跑一遍得出最短路
	for(int i=q[n];i;i=q[A[i].next]){   //删掉最短路中的一条路
		SPFA(i);                       //再跑一遍。
		ans=max(ans,f[n]);
	}
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_42937087/article/details/89214836
今日推荐