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

但是这样是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

 

posted on 2015-05-09 17:14  acphile  阅读(188)  评论(0编辑  收藏  举报