版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sulvshuo/article/details/76776480
【2017.8.6普及模拟】最大(max)
(File IO): input:max.in output:max.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet
题目描述
走进丛林的BT开始了他在丛林的探险,一天晚上,BT坐在篝火旁,无聊地看着地图,他在回忆着进入丛林的经过……
他发现,丛林的每棵树上都有些浆果,这些浆果都是他没见过的,所以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
数据范围限制
数据:数据保证所有数(包括答案)在long long(pascal的
Int64)范围内(即小于2^63)
正解
二分+最短路。
就是二分找一个答案,用最短路看它是否合法,如果合法,在从更小的范围中去找他。否则从更大的范围去找,因为将范围扩大不会将原来已经扩展开的路关上,所以说,这题是可以用二分的。
那么正解就很容易得到了。
代码
var
n,m,s1,s2,ks,i,s,t,st,l,r,mid,p,long,u,ans,t1,t2:longint;
//:array[1..25000] of longint;
a,b,d,q,g:array[1..20000] of longint;
h:array[1..10000,1..100,1..2] of int64;
procedure qsort(l,r:longint);
var
i,j,mid,t:longint;
begin
i:=l;
j:=r;
mid:=a[(i+j) div 2];
repeat
while (a[i]<mid) do inc(i);
while (a[j]>mid) do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then
qsort(i,r);
if l<J then
qsort(l,j);
end;
begin
assign(input,'max.in');
assign(output,'max.out');
reset(input);
rewrite(output);
read(n,m,s1,s2,ks);
for i:=1 to n do
begin
read(a[i]);
end;
b:=a;
t1:=a[s1];
t2:=a[s2];
qsort(1,n);
for i:=1 to m do
begin
read(s,t,st);
inc(g[s]);
h[s,g[s],1]:=t;
h[s,g[s],2]:=st;
inc(g[t]);
h[t,g[t],1]:=s;
h[t,g[t],2]:=st;
end;
for i:=1 to n do
begin
if (a[i]=t1) or (a[i]=t2) then
l:=i;
end;
r:=n;
while (l<=r) do
begin
mid:=(l+r) div 2;
for i:=1 to n do
q[i]:=i;
for i:=1 to n do
d[i]:=maxlongint;
d[s1]:=0;
p:=s1;
long:=n;
while (p<=long) do
begin
u:=q[p];
for i:=1 to g[u] do
begin
if (d[h[u,i,1]]>d[u]+h[u,i,2])
and (b[h[u,i,1]]<=a[mid]) then
begin
d[h[u,i,1]]:=d[u]+h[u,i,2];
inc(long);
q[long]:=h[u,i,1];
end;
end;
inc(p);
end;
if d[s2]<=ks div 2 then
begin
r:=mid-1;
end
else
begin
l:=mid+1;
end;
end;
writeln(a[l]);
close(input);
close(output);
end.