http://acm.hdu.edu.cn/showproblem.php?pid=1595
大致题意:
给一个图。让输出从中删除随意一条边后所得最短路径中最长的。
。
思路:
直接枚举每条边想必是不行的。事实上有些边是不须要枚举的,由于删除它们并不影响起点到终点的最短路。起作用的边都是未删边前的最短路径上的边,删除它们最短距离肯定增大,仅仅需在这些最短距离中求最大的就可以。
记录最短路径上的边,仅仅需一个pre数组记录松弛时每一个点的前驱节点。
#include <stdio.h> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h> #include <string.h> #define LL long long #define _LL __int64 using namespace std; const int maxn = 1010; const int INF = 0x3f3f3f3f; int n,m; int mapp[1010][1010]; int dis[maxn],vis[maxn]; int pre[maxn],pre1[maxn]; int ans; void init() { for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(i == j) mapp[i][j] = 0; else mapp[i][j] = INF; } } memset(pre,-1,sizeof(pre)); } int dijstra(int s) { memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); for(int i = 1; i <= n; i++) { dis[i] = mapp[s][i]; pre[i] = s; } vis[s] = 1; pre[s] = -1; for(int i = 1; i < n; i++) { int min = INF,pos; for(int j = 1; j <= n; j++) { if(min > dis[j] && !vis[j]) { min = dis[j]; pos = j; } } vis[pos] = 1; for(int j = 1; j <= n; j++) { if(!vis[j] && dis[j] > dis[pos] + mapp[pos][j]) { dis[j] = dis[pos] + mapp[pos][j]; pre[j] = pos; } } } return dis[n]; } void solve() { memcpy(pre1,pre,sizeof(pre)); ans = -1; int u = n; while(pre1[u] != -1) { int tmp = mapp[pre1[u]][u]; mapp[pre1[u]][u] = mapp[u][pre1[u]] = INF; //删除该边 int res = dijstra(1); if(res != INF) ans = max(ans,res); mapp[ pre1[u] ][u] = mapp[u][ pre1[u] ] = tmp; u = pre1[u]; } printf("%d\n",ans); } int main() { int u,v,w; while(~scanf("%d %d",&n,&m)) { init(); for(int i = 0; i < m; i++) { scanf("%d %d %d",&u,&v,&w); mapp[u][v] = mapp[v][u] = min(w,mapp[u][v]); } dijstra(1); solve(); } return 0; }