这道题要谈很多;
首先,第一问等会我另外说一下;
第二问比较难想,首先我们的考虑两人的最优策略是什么
对于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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.