他发现,丛林的每棵树上都有些浆果,这些浆果都是他没见过的,所以BT想把这些果子都拿回去做研究,然而BT认为一次那太多会很不爽,所以他想知道,他从营地到准备考察的地方,一每棵树上的浆果最大值的最小值。当然,BT的早餐能量有限,而从一棵树到另一棵树所需能量是已知的,BT要保证来回所需能量小于等于早餐所提供的能量。
输入: 第一行5个正整数,n(1<=n<=10000),m(1<=m<=25000),s,t,st。分别表示有n棵树,m条路径,从营地s到考察处t,早餐的能量为st。接下来有n行,每行1个正整数,fi。表示第i棵树上的浆果重量。 再接下来有m行,每行3个正整数,x,y,d (1<=x,y<=n)。表示第x棵树和第y棵树之间可通行,且所需能量为d。
输出:一行,路径上浆果重量最大值的最小值。若BT无法从营地和考察地间走一个来回,则输出-1。
样例输入:
4 4 2 3 8 8 5 6 10 2 1 2 2 4 1 1 3 4 3 4 3
样例输出:
10
其实这道题是一道破坏OJ平衡性的水题!
思路:二分(为什么在比赛时没想到呢????)+SPFA(伟大的SPFA)。
先二分出一个答案,再用SPFA判断此答案符不符合条件,至于那个早餐能量,(完全扯淡!)直接一开始的时候把它 div 2就行了。
代码:
var n,m,i,j,k,x,y,z,s,ls,o,p,nl,l,r,mid:longint; f:array[0..10001,0..1001,1..2]of longint; a:array[0..10001]of longint; function pd(k:longint):boolean; var d,t:array[0..10001]of longint; i,j,x,y,z,s,l:longint; begin for i:=1 to 10000 do t[i]:=maxlongint; t[o]:=0; d[1]:=o; i:=0; j:=1; while i<j do begin inc(i); for l:=1 to f[d[i],0,1] do if a[f[d[i],l,1]]<=k then begin if t[f[d[i],l,1]]>t[d[i]]+f[d[i],l,2] then begin inc(j); d[j]:=f[d[i],l,1]; t[f[d[i],l,1]]:=t[d[i]]+f[d[i],l,2]; end; end; end; if (t[p]<>maxlongint)and(t[p]<=ls) then exit(true) else exit(false); end; begin assign(input,'max.in'); reset(input); assign(output,'max.out'); rewrite(output); readln(n,m,o,p,ls); ls:=ls div 2; for i:=1 to n do readln(a[i]); for i:=1 to m do begin readln(x,y,z); inc(f[x,0,1]); f[x,f[x,0,1],1]:=y; f[x,f[x,0,1],2]:=z; inc(f[y,0,1]); f[y,f[y,0,1],1]:=x; f[y,f[y,0,1],2]:=z; end; l:=a[o]; r:=maxlongint-l; while l<=r do begin mid:=(l+r) div 2; if pd(mid) then begin s:=mid; r:=mid-1; end else l:=mid+1; end; if s=0 then writeln(-1) else writeln(s); end.
