这道题要谈很多;

首先,第一问等会我另外说一下;

第二问比较难想,首先我们的考虑两人的最优策略是什么

对于Bob,我们令分配了x条边的费用,则我们要最大化

ans=Σ(i=1 to x) flow[i] * p/x  (flow[i]为选择的边)

显然ans<=x*maxflow[i]*p/x=maxflow[i]*p 

显然ans最大的方案就是将费用全部分配到实际流量最大的那条边上去

这样Alice的方案也明确了,就是在维持最大流不变的前提下,是实际流量最大的那条边最小

对于这类最小化最大的问题,我们不难想到二分答案,二分网络流上界流量

但请注意,有没有从题目保留的精度想到什么呢?

对,这道题流量可以是实数,

对于任意实数的网络流是不可做的,但是在一定精度范围内就照样可行;

照样就没什么问题了

这里说下我发现我以前写的最大流sap是不够好的

没加当前弧优化,之前很多题没TLE真是万幸;

在bzoj2127(之后放在一个专题写)中体现的特别明显,如果只用sap+gap妥妥TLE

用了之后1s多跑完……

这里给出最终的最大流写法(sap+gap+cur)

  1 const inf=500000007;
  2       ok=1e-6;  //控制精读
  3 type node=record
  4        next,point:longint;
  5        flow:double;
  6      end;
  7 
  8 var edge:array[0..20100] of node;
  9     cur,numh,p,h,pre:array[0..150] of longint;
 10     w,x,y:array[0..2010] of longint;
 11     d:array[0..150] of double;
 12     l,r,mid,ans1,ans2:double;
 13     t,len,i,n,m:longint;
 14 
 15 function min(a,b:double):double;
 16   begin
 17     if a>b then exit(b) else exit(a);
 18   end;
 19 
 20 procedure add(x,y:longint;f:double);
 21   begin
 22     inc(len);
 23     edge[len].flow:=f;
 24     edge[len].point:=y;
 25     edge[len].next:=p[x];
 26     p[x]:=len;
 27   end;
 28 
 29 function sap(k:double):double;  //带当前弧优化
 30   var u,i,j,tmp,q:longint;
 31       neck:double;
 32       flag:boolean;
 33   begin
 34     len:=-1;
 35     fillchar(p,sizeof(p),255);
 36     for i:=1 to m do
 37     begin
 38       add(x[i],y[i],min(k,w[i]));
 39       add(y[i],x[i],0);
 40     end;
 41     fillchar(numh,sizeof(numh),0);
 42     fillchar(h,sizeof(h),0);
 43     numh[0]:=n;
 44     u:=1;
 45     neck:=inf;
 46     sap:=0;
 47     cur:=p;
 48     while h[1]<n do
 49     begin
 50       d[u]:=neck;
 51       flag:=false;
 52       i:=cur[u];
 53       while i<>-1 do
 54       begin
 55         j:=edge[i].point;
 56         if (edge[i].flow>0) and (h[u]=h[j]+1) then
 57         begin
 58           flag:=true;
 59           cur[u]:=i;
 60           pre[j]:=u;
 61           neck:=min(neck,edge[i].flow);
 62           u:=j;
 63           if u=n then
 64           begin
 65             sap:=sap+neck;
 66             while u<>1 do
 67             begin
 68               u:=pre[u];
 69               j:=cur[u];
 70               edge[j].flow:=edge[j].flow-neck;
 71               edge[j xor 1].flow:=edge[j xor 1].flow+neck;
 72             end;
 73             neck:=inf;  //勿忘1
 74           end;
 75           break;
 76         end;
 77         i:=edge[i].next;
 78       end;
 79       if not flag then
 80       begin
 81         dec(numh[h[u]]);
 82         if numh[h[u]]=0 then exit;
 83         tmp:=n;
 84         i:=p[u];
 85         q:=0;
 86         while i<>-1 do
 87         begin
 88           j:=edge[i].point;
 89           if (tmp>h[j]) and (edge[i].flow>0) then
 90           begin
 91             q:=i;
 92             tmp:=h[j];
 93           end;
 94           i:=edge[i].next;
 95         end;
 96         h[u]:=tmp+1;
 97         cur[u]:=q;     //勿忘2
 98         inc(numh[h[u]]);
 99         if u<>1 then
100         begin
101           u:=pre[u];
102           neck:=d[u];   //记录当前瓶颈边的作用
103         end;
104       end;
105     end;
106   end;
107 
108 begin
109   readln(n,m,t);
110   for i:=1 to m do
111   begin
112     readln(x[i],y[i],w[i]);
113     if r<w[i] then r:=w[i];
114   end;
115   l:=0;
116   ans1:=sap(r);
117   while r-l>ok do   //实数范围内的二分答案
118   begin
119     mid:=(l+r)/2;
120     if abs(ans1-sap(mid))<ok then r:=mid
121     else l:=mid;
122   end;
123   writeln(ans1:0:0);
124   writeln(r*t:0:4);
125 end.
View Code

 

posted on 2014-06-03 23:21  acphile  阅读(179)  评论(0编辑  收藏  举报