这两题本质是一致的;

一般来说,对于最长(短)化最短(长)的问题我们一般都使用二分答案+判定是否可行

因为这样的问题,我们一旦知道答案,就能知道全局信息

拿poj2455举例,对于二分出的一个答案,我们将不符合的边全部去掉,在做一遍最大流判断是否成立即可

注意这道题有重边,所以用链式前向星比较好(TT,当时我用的数组模拟邻接表表不要太烦)

  1 type node=record
  2        po,flow,cost:longint;
  3      end;
  4 var w,ow:array[0..205,0..5000] of node;
  5     cur,pre,numh,h,s,s0:array[0..500] of longint;
  6     ans,max,mid,l,r,x,y,z,i,n,m,p:longint;
  7 
  8 procedure add(x,y,z,f:longint);  //很繁琐的结构,需要检查好久,重边优先选择链式前向星,比较方便
  9   begin
 10     inc(s[x]);
 11     w[x,s[x]].po:=y;
 12     w[x,s[x]].cost:=z;
 13     w[x,s[x]].flow:=f;
 14   end;
 15 
 16 function maxflow(k:longint):boolean;  //很喜欢写sap,判定
 17   var j,sum,u,i,t,r,tmp:longint;
 18   begin
 19     max:=-1;
 20     fillchar(pre,sizeof(pre),255);
 21     fillchar(cur,sizeof(cur),255);
 22     fillchar(h,sizeof(h),0);
 23     fillchar(numh,sizeof(numh),0);   //一定要注意,这句话没有不影响程序结果,但会拖慢程序速度(相当于没用到GAP优化),谨记
 24     fillchar(s0,sizeof(s0),0);
 25     for i:=1 to n do
 26       for j:=1 to s[i] do
 27       begin
 28         if w[i,j].cost<=k then     //根据条件构造新图
 29         begin
 30           inc(s0[i]);
 31           ow[i,s0[i]]:=w[i,j];
 32         end;
 33       end;
 34     numh[0]:=n;
 35     sum:=0;
 36     u:=1;
 37     while h[1]<n do
 38     begin
 39       if u=n then
 40       begin
 41         i:=1;
 42         while i<>n do
 43         begin
 44           t:=cur[i];
 45           if max<ow[i,t].cost then max:=ow[i,t].cost;  //小优化而已,在最大流里面找一条最大的边,实际上答案是这个
 46           dec(ow[i,t].flow);
 47           i:=ow[i,t].po;
 48         end;
 49         inc(sum);
 50         if sum=p then exit(true);
 51         u:=1;
 52       end;
 53       r:=-1;
 54       for i:=1 to s0[u] do
 55         if (ow[u,i].flow>0) and (h[u]=h[ow[u,i].po]+1) then
 56         begin
 57           r:=i;
 58           break;
 59         end;
 60 
 61       if r<>-1 then
 62       begin
 63         cur[u]:=r;
 64         pre[ow[u,r].po]:=u;
 65         u:=ow[u,r].po;
 66       end
 67       else begin
 68         dec(numh[h[u]]);
 69         if numh[h[u]]=0 then exit(false);   
 70         tmp:=n;   //注意这里千万不要顺手打成maxlongint之类
 71         for i:=1 to s0[u] do
 72           if (ow[u,i].flow>0) and (tmp>h[ow[u,i].po]) then tmp:=h[ow[u,i].po];
 73         h[u]:=tmp+1;
 74         inc(numh[h[u]]);
 75         if u<>1 then u:=pre[u];
 76       end;
 77     end;
 78     exit(false);
 79   end;
 80 
 81 begin
 82   readln(n,m,p);
 83   for i:=1 to m do
 84   begin
 85     readln(x,y,z);
 86     add(x,y,z,1);
 87     add(y,x,z,1);
 88     if z>r then r:=z;
 89   end;
 90   l:=1;
 91   while l<=r do
 92   begin
 93     mid:=(l+r) shr 1;
 94     if maxflow(mid) then  
 95     begin
 96       ans:=max;   //小小的优化,但不是所有二分判定都可以用
 97       r:=max-1;
 98     end
 99     else l:=mid+1;
100   end;
101   writeln(ans);
102 end.
View Code

poj2391也是一样的,只不过多了floyd预处理

一般的,对于答案越大,决策就越有可能成功的这类具有单调性的题目,通常使用二分答案

 

posted on 2014-03-16 22:51  acphile  阅读(155)  评论(0编辑  收藏  举报