bzoj 1614 二分+最短路

题意:找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。 电信公司最终同意免费为FJ连结K对由FJ指定的电话线杆。对于此外的那些电话线,要求最大边最小
明显的二分答案,因为只要求1号和n号连起来,其他点不要求,所以跑最短路即可
对于二分出mid,我们check时,找到1号到n号的最短路中,边权大于mid的边是否小于等于K,如果满足则为true否则为false
所以对于大于mid的边我们连边权为1,小于等于mid的边连边权为0,
              最后dis[n]就是最短路中边权大于mid的边的条数
type
        rec=record
            x,y,z:longint;
end;

var
        n,m,p,l,ans    :longint;
        ll,mid,rr      :longint;
        e              :array[0..10010] of rec;
        vis            :array[0..1010] of boolean;
        pre,other,len  :array[0..20010] of longint;
        que,dis,last   :array[0..1010] of longint;
        i              :longint;
procedure connect(x,y,z:longint);
begin
   inc(l);
   pre[l]:=last[x];
   last[x]:=l;
   other[l]:=y;
   len[l]:=z;
end;

procedure spfa;
var
        q,p,cur,h,tl:longint;
begin
   h:=0; tl:=1; que[1]:=1; dis[1]:=0;
   while (h<>tl) do
   begin
      h:=h mod 1005+1;
      cur:=que[h];
      vis[cur]:=false;
      q:=last[cur];
      while (q<>0) do
      begin
         p:=other[q];
         if dis[p]>dis[cur]+len[q] then
         begin
            dis[p]:=dis[cur]+len[q];
            if not vis[p] then
            begin
               vis[p]:=true;
               tl:=tl mod 1005+1;
               que[tl]:=p;
            end;
         end;
         q:=pre[q];
      end;
   end;
end;

function check(x:longint):boolean;
begin
   l:=0;
   fillchar(last,sizeof(last),0);
   fillchar(vis,sizeof(vis),false);
   fillchar(dis,sizeof(dis),127);
   for i:=1 to m do
     if (e[i].z>x) then
     begin
        connect(e[i].x,e[i].y,1);
        connect(e[i].y,e[i].x,1);
     end else
     begin
        connect(e[i].x,e[i].y,0);
        connect(e[i].y,e[i].x,0);
     end;
   spfa;
   if dis[n]<=p then exit(true) else exit(false);
end;

begin
   read(n,m,p);
   ll:=0; rr:=0; ans:=maxlongint;
   for i:=1 to m do
   begin
      read(e[i].x,e[i].y,e[i].z);
      if rr>1;
      if check(mid) then
      begin
         if mid
——by Eirlys
bzoj 1614 二分+最短路_第1张图片

你可能感兴趣的:(最短路,二分,bzoj)