题目:
这是一个风和日丽的日子,桐人和诗乃在约会。他们所在的城市共有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);//输出
}