玛丽卡(wikioi1021)
【题目描述 】
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
【输入描述】
第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。
接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。
【输出描述】
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
【样例输入】
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10
样例输出
27
分析:
初看题目,第一个就会想到枚举堵车的道路将其删去后求最短路径,但写了之后发现超时了,这说明需要优化,可以先求出n到1的最短路径,如果堵车的道路不再最短路径上删去后对结果就没有影响,此时最短路径没有被破坏,还是原来的路径,故只需枚举最短路径上的道路删去即可,可以在第一遍SPFA时记录路径,然后枚举。注意记录前驱的语句的位置,我就被这个坑了...
代码:
program mary; var a:array[0..1000,0..10000]of longint; q,p:array[0..200000]of longint; w:array[0..1000,0..1000]of longint; dis:array[0..1000]of longint; g:array[0..1000]of boolean; n,i,m,j,x,y,z,max:longint; procedure spfa(x,y:longint); var i,u,v,h,t:longint; begin for i:=1 to n do dis[i]:=maxlongint div 3; fillchar(g,sizeof(g),false); fillchar(q,sizeof(q),0); if x=0 then fillchar(p,sizeof(p),0); h:=0; t:=1; dis[n]:=0; q[1]:=n; g[n]:=true; if x=0 then p[n]:=n; while h<t do begin h:=h+1; u:=q[h]; g[u]:=false; for i:=1 to a[u,0] do if (u<>x)or(a[u,i]<>y) then begin v:=a[u,i]; if dis[v]>dis[u]+w[u,v] then begin dis[v]:=dis[u]+w[u,v]; if x=0 then p[v]:=u; if g[v]=false then begin t:=t+1; q[t]:=v; g[v]:=true; end; end; end; end; if dis[1]>max then max:=dis[1]; end; begin readln(n,m); for i:=1 to n do for j:=1 to n do w[i,j]:=maxlongint div 3; for i:=1 to m do begin readln(x,y,z); inc(a[x,0]); a[x,a[x,0]]:=y; inc(a[y,0]); a[y,a[y,0]]:=x; w[x,y]:=z; w[y,x]:=z; end; spfa(0,0); max:=0; j:=1; while j<>n do begin spfa(p[j],j); j:=p[j]; end; writeln(max); end.
原文:http://www.cnblogs.com/qtyytq/p/4372894.html