最大

版权声明:本文为博主原创文章,未经博主允许不得转载。 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.

猜你喜欢

转载自blog.csdn.net/sulvshuo/article/details/76776480