桐人的约会
题目大意:
删掉一条边,让一个图中的最短路最长
原题:
题目描述
这是一个风和日丽的日子,桐人和诗乃在约会。他们所在的城市共有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
说明
【数据规模】
30% N<=5, M<=10
60% N<=1000,M<=10000,w=1
100% N<=1000, M<=N*(N-1)/2,1<=w<=1000
解题思路:
先找到最短路,然后将最短路中的每一段路依次删掉,每删掉一次跑一遍SPFA
代码:
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,w,h,x,y,c,ans,p[1005],b[1005],la[1005],las[1005],head[1005];
struct rec
{int l,to,next,pd;
}a[2000005];
void SPFA(int now)
{a[now].pd=1;//去掉memset(b,127/3,sizeof(b));queue<int>d;//SPFAd.push(1);p[1]=1;b[1]=0;while(!d.empty()){h=d.front();d.pop();for (int i=head[h];i;i=a[i].next)if (b[h]+a[i].l<b[a[i].to]&&(!a[i].pd)){b[a[i].to]=b[h]+a[i].l;if (!p[a[i].to]){p[a[i].to]=1;d.push(a[i].to);}}p[h]=0;}a[now].pd=0;//返回ans=max(ans,b[n]);//取最大值
}
void spfa()//SPFA
{memset(b,127/3,sizeof(b));queue<int>d;d.push(1);p[1]=1;b[1]=0;while(!d.empty()){h=d.front();d.pop();for (int i=head[h];i;i=a[i].next)if (b[h]+a[i].l<b[a[i].to]){b[a[i].to]=b[h]+a[i].l;las[a[i].to]=h;//前缀la[a[i].to]=i;//相连接的线if (!p[a[i].to]){p[a[i].to]=1;d.push(a[i].to);}}p[h]=0;}for (int i=n;i>1;i=las[i])SPFA(la[i]);//删掉这条线路再跑最短路
}
int main()
{scanf("%d %d",&n,&m);for (int i=1;i<=m;++i){scanf("%d %d %d",&x,&y,&c);a[++w].to=y;//存储a[w].l=c;a[w].next=head[x];head[x]=w;a[++w].to=x;a[w].l=c;a[w].next=head[y];head[y]=w;}spfa();//最短路printf("%d",ans);
}