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 }
View Code

 

posted @ 2018-04-18 17:48  鲸头鹳  阅读(159)  评论(0编辑  收藏  举报