题目链接
题意:给出n个点,m条边,求去除任意一条边的最长最短路。
这题先用求一次最短路,记录下路径。如果去除的边不在路径上,那么最短路不变。所以我们只要考虑去除最短路上的边的情况。枚举最短路上的边删除,求最短路,注意要还原边。
这题用spfa的邻接矩阵形式怎么也过不了,一直TLE。代码不变,换成dijkstra之后就能过了。
ps:SPFA算法在负边权图上可以完全取代Bellman-ford算法,另外在稀疏图中也表现良好。但是在非负边权图中,为了避免最坏情况的出现,通常使用效率更加稳定的Dijkstra算法,以及它的使用堆优化的版本。通常的SPFA算法在一类网格图中的表现不尽如人意。
dijkstra,floyd,bellman-ford,spfa算法比较:传送门
#include <iostream> #include<cstdio> #include<cmath> #include<cstring> #include<queue> #define N 1100 #define INF 0x7ffffff using namespace std; int d[N],pre[N],v[N],n,m,mp[N][N]; /*void spfa(int t) { for(int i=1;i<=n;i++) d[i]=INF,v[i]=0; queue<int> q; q.push(1); v[1]=1; d[1]=0; while(!q.empty()) { int c=q.front(); q.pop(); v[c]=0; for(int i=1;i<=n;i++) { if(d[i]>d[c]+mp[c][i]) { d[i]=d[c]+mp[c][i]; if(t) pre[i]=c; if(!v[i]) v[i]=1,q.push(i); } } } }*///TLE void dijkstra(int c) { for(int i=0;i<=n;i++) d[i]=INF,v[i]=0; d[1]=0; for(int i=1;i<=n;i++) { int t=-1,mmin=INF; for(int j=1;j<=n;j++) if(!v[j]&&mmin>d[j]) mmin=d[t=j]; if(t==-1) break; v[t]=1; for(int j=1;j<=n;j++) if(d[j]>d[t]+mp[t][j]) { d[j]=d[t]+mp[t][j]; if(c) pre[j]=t; } } }//AC int main() { while(~scanf("%d%d",&n,&m)) { for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) mp[i][j]=INF; for(int i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); mp[u][v]=mp[v][u]=w; } memset(pre,-1,sizeof(pre)); dijkstra(1); int ans=d[n]; for(int i=n;i!=1;i=pre[i]) { int t=mp[i][pre[i]]; mp[i][pre[i]]=mp[pre[i]][i]=INF; dijkstra(0); if(d[n]>ans) ans=d[n]; mp[i][pre[i]]=mp[pre[i]][i]=t; } cout<<ans<<endl; } }