BZOJ 3130: [Sdoi2013]费用流 网络流 二分 最大流
https://www.lydsy.com/JudgeOnline/problem.php?id=3130
本来找费用流的题,权当复习一下网络流好了。
有点麻烦的是double,干脆判断大小或者二分增加下限都用eps=1e-8操作好了(毕竟只要求精确到4位)。
我普通最大流都快忘了,板子写错了一次超时了。
网络流板子的细节要记清楚:1.增广的时候访问完哪个点就把dep标记改为-1防止同一次增广再次访问。2.往下层传递的时候用val-cnt而不是val。3.cnt=val时及时返回。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=1010; 9 const double eps=1e-8; 10 int n,m,p;double mx; 11 struct nod{ 12 int y,rev,next;double v,v1; 13 }e[maxn*2]; 14 int head[maxn]={},tot=0;double Ans=0; 15 int num[maxn]={},vis[maxn*2]={}; 16 queue<int>q; 17 void init(int x,int y,double v){ 18 e[++tot].y=y;e[tot].v=v;e[tot].rev=tot+1;e[tot].next=head[x];head[x]=tot; 19 e[++tot].y=x;e[tot].v=0;e[tot].rev=tot-1;e[tot].next=head[y];head[y]=tot; 20 } 21 bool fir(){ 22 memset(num,-1,sizeof(num)); 23 q.push(1);num[1]=0; 24 while(!q.empty()){ 25 int x=q.front();q.pop(); 26 for(int i=head[x];i;i=e[i].next){ 27 if(e[i].v1<eps)continue; 28 if(num[e[i].y]==-1){ 29 num[e[i].y]=num[x]+1; 30 q.push(e[i].y); 31 } 32 } 33 } 34 return num[n]!=-1; 35 } 36 double dfs(int x,double val){ 37 if(x==n)return val; 38 double cnt=0,z; 39 for(int i=head[x];i;i=e[i].next){ 40 if((e[i].v1<eps)||num[e[i].y]!=num[x]+1)continue; 41 z=dfs(e[i].y,min(val-cnt,e[i].v1)); 42 cnt+=z; e[i].v1-=z; e[e[i].rev].v1+=z; 43 if(val-cnt<eps)return cnt; 44 }num[x]=-1; 45 return cnt; 46 } 47 bool Check(double shu){ 48 mx=shu;double cnt=0; 49 for(int i=1;i<tot;i+=2)e[i].v1=min(mx,e[i].v); 50 for(int i=2;i<=tot;i+=2)e[i].v1=0; 51 while(fir()){ 52 cnt+=dfs(1,50000000); 53 } 54 return Ans-cnt<eps; 55 } 56 double erfen(double mx){ 57 double l=0,r=mx; 58 while(r-l>eps){ 59 double mid=(l+r)/2; 60 if(Check(mid))r=mid; 61 else l=mid+eps; 62 } 63 return l; 64 } 65 int main(){ 66 scanf("%d%d%d",&n,&m,&p); 67 int x,y,z; 68 for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);init(x,y,(double)z);mx=max(mx,(double)z);} 69 for(int i=1;i<=tot;i++)e[i].v1=e[i].v; 70 while(fir())Ans+=dfs(1,mx); 71 if(Ans==0){ 72 printf("0\n0.0000\n"); 73 } 74 else{ 75 printf("%.0f\n",Ans); 76 printf("%.4lf\n",erfen(mx)*(double)p); 77 } 78 return 0; 79 }