zoukankan      html  css  js  c++  java
  • bzoj1532

    就题目而言,这道题是裸的二分+最大流

    但是这样是TLE的,我们考虑优化

    1. 我们可以先贪心,这样二分的上界就可以缩小了

    2. 最大流我们可以不急着跑增广路,我们可以先贪心一个流然后再跑增广路

    但是我们发现上述优化还是不足以通过这题

    我们考虑是不是sap不适合处理这张图(这是二分图)呢?确实是这样的

    考虑到sap判断h[s]<t+1,但实际上二分图的增广路不可能太长,我们把这个条件改成h[s]<100

    duang的一下,就飞快的跑过了(460ms)

    而事实证明dinic似乎没有这种问题,因为根据证明,dinic跑二分图和HK算法是一样的复杂度

      1 type node=record
      2        po,next,flow:longint;
      3      end;
      4 
      5 var e:array[0..200010] of node;
      6     w,pre,numh,p,h,cur,x,y:array[0..20010] of longint;
      7     ans,t,i,n,m,l,r,mid,len,need:longint;
      8 
      9 procedure add(x,y,f:longint);
     10   begin
     11     inc(len);
     12     e[len].po:=y;
     13     e[len].flow:=f;
     14     e[len].next:=p[x];
     15     p[x]:=len;
     16   end;
     17 
     18 procedure build(x,y,f1,f2:longint);
     19   begin
     20     add(x,y,f1);
     21     add(y,x,f2);
     22   end;
     23 
     24 function sap:longint;
     25   var i,j,q,u,tmp:longint;
     26   begin
     27     fillchar(numh,sizeof(numh),0);
     28     fillchar(h,sizeof(h),0);
     29     for i:=0 to t do
     30       cur[i]:=p[i];
     31     u:=0; sap:=0;
     32     while (h[0]<t+1) and (h[0]<100) do  //重要优化
     33     begin
     34       i:=cur[u];
     35       while i<>-1 do
     36       begin
     37         j:=e[i].po;
     38         if (e[i].flow>0) and (h[u]=h[j]+1) then
     39         begin
     40           cur[u]:=i;
     41           pre[j]:=u;
     42           u:=j;
     43           if u=t then
     44           begin
     45             inc(sap);
     46             if sap=need then exit;
     47             while u<>0 do
     48             begin
     49               u:=pre[u];
     50               j:=cur[u];
     51               dec(e[j].flow);
     52               inc(e[j xor 1].flow);
     53             end;
     54           end;
     55           break;
     56         end;
     57         i:=e[i].next;
     58       end;
     59       if i=-1 then
     60       begin
     61         dec(numh[h[u]]);
     62         if numh[h[u]]=0 then exit;
     63         i:=p[u];
     64         tmp:=t;
     65         q:=-1;
     66         while i<>-1 do
     67         begin
     68           j:=e[i].po;
     69           if e[i].flow>0 then
     70             if tmp>h[j] then
     71             begin
     72               q:=i;
     73               tmp:=h[j];
     74             end;
     75           i:=e[i].next;
     76         end;
     77         h[u]:=tmp+1;
     78         inc(numh[h[u]]);
     79         cur[u]:=q;
     80         if u<>0 then u:=pre[u];
     81       end;
     82     end;
     83   end;
     84 
     85 procedure swap(var a,b:longint);
     86   var c:longint;
     87   begin
     88     c:=a;
     89     a:=b;
     90     b:=c;
     91   end;
     92 
     93 function check(h:longint):boolean;
     94   var i:longint;
     95   begin
     96     len:=-1;
     97     fillchar(p,sizeof(p),255);
     98     need:=0;
     99     for i:=1 to n do
    100       w[i]:=h;
    101     for i:=1 to m do  //贪心初始流
    102     begin
    103       if w[x[i]]<w[y[i]] then swap(x[i],y[i]);
    104       if w[x[i]]=0 then
    105       begin
    106         build(i,x[i]+m,1,0);
    107         build(0,i,1,0);
    108         inc(need);
    109       end
    110       else begin
    111         dec(w[x[i]]);
    112         build(0,i,0,1);
    113         build(i,x[i]+m,0,1);
    114       end;
    115       build(i,y[i]+m,1,0);
    116     end;
    117     if need=0 then exit(true);
    118     for i:=1 to n do
    119       build(i+m,t,w[i],h-w[i]);
    120     if sap=need then exit(true) else exit(false);
    121   end;
    122 
    123 begin
    124   readln(n,m);
    125   for i:=1 to m do
    126   begin
    127     readln(x[i],y[i]);
    128     if w[x[i]]<w[y[i]] then inc(w[x[i]]) else inc(w[y[i]]);
    129   end;
    130   for i:=1 to n do
    131     if w[i]>r then r:=w[i];  //贪心上界
    132   t:=n+m+1;
    133   l:=0;
    134   while l<=r do
    135   begin
    136     mid:=(l+r) shr 1;
    137     if check(mid) then
    138     begin
    139       ans:=mid;
    140       r:=mid-1;
    141     end
    142     else l:=mid+1;
    143   end;
    144   writeln(ans);
    145 end.
    View Code
  • 相关阅读:
    有序表查找
    遍历二叉树
    二叉树
    [Oracle]使用InstantClient访问Oracle数据库
    [部署]CentOS yum源
    [部署]CentOS安装PHP环境
    [部署]CentOS安装MariaDB
    [部署]CentOS安装apache
    Metrics.NET源码阅读笔记
    [JavaScript]catch(ex)语句中的ex
  • 原文地址:https://www.cnblogs.com/phile/p/4490710.html
Copyright © 2011-2022 走看看