这两题本质是一致的;
一般来说,对于最长(短)化最短(长)的问题我们一般都使用二分答案+判定是否可行
因为这样的问题,我们一旦知道答案,就能知道全局信息
拿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.
poj2391也是一样的,只不过多了floyd预处理
一般的,对于答案越大,决策就越有可能成功的这类具有单调性的题目,通常使用二分答案