「luogu3705」[SDOI2017]新生舞会

01分数规划。

二分答案+费用流。

注意eps赋为1e-7会wa。。。

 1 #include<bits/stdc++.h>
 2 #define db double
 3 using namespace std;
 4 const int N=110,E=11000,oo=INT_MAX;
 5 const db eps=1e-8;
 6 int n,ss,tt,a[N][N],b[N][N];
 7 int from[E<<1],to[E<<1],flow[E<<1],edge_tot;
 8 db cap[E<<1],cost[E<<1];
 9 vector<int>point[N<<1];
10 void add_edge(int f,int t,db c,db cc){
11     from[edge_tot]=f,to[edge_tot]=t,cap[edge_tot]=c,cost[edge_tot]=cc;
12     point[f].push_back(edge_tot++);
13     from[edge_tot]=t,to[edge_tot]=f,cap[edge_tot]=0,cost[edge_tot]=-cc;
14     point[t].push_back(edge_tot++);
15     return;
16 }
17 db dis[N<<1];
18 int pre[N<<1];
19 bool inq[N<<1];
20 bool spfa(){
21     for(int i=1;i<=tt;i++) dis[i]=-oo;
22     queue<int>q;
23     q.push(ss);
24     dis[ss]=0,inq[ss]=1;
25     int x,nxte;
26     while(!q.empty()){
27         x=q.front();q.pop();
28         inq[x]=0;
29         for(int i=0;i<point[x].size();i++){
30             nxte=point[x][i];
31             if(cap[nxte]>flow[nxte]&&dis[to[nxte]]<dis[x]+cost[nxte]){
32                 dis[to[nxte]]=dis[x]+cost[nxte],pre[to[nxte]]=nxte;
33                 if(!inq[to[nxte]]){
34                     q.push(to[nxte]);
35                     inq[to[nxte]]=1;
36                 } 
37             }
38         }
39     }
40     return dis[tt]>-oo;
41 }
42 inline void reset(){
43     for(int i=0;i<edge_tot;i++) flow[i]=0;
44     return;
45 }
46 db maxcostmaxflow(){
47     db ans=0;
48     while(spfa()){
49         db minf=oo;
50         int now=tt;
51         while(now!=ss){
52             minf=min(minf,cap[pre[now]]-flow[pre[now]]);
53             now=from[pre[now]];
54         }
55         ans+=minf*dis[tt],now=tt;
56         while(now!=ss){
57             flow[pre[now]]+=minf,flow[pre[now]^1]-=minf;
58             now=from[pre[now]];
59         }
60     }
61     reset();
62     return ans;
63 }
64 int main(){
65     scanf("%d",&n);
66     db l=0,r=0,ans=-oo;
67     ss=2*n+1,tt=ss+1;
68     for(int i=1;i<=n;i++){
69         for(int j=1;j<=n;j++){scanf("%d",&a[i-1][j-1]);add_edge(i,j+n,1,0);}
70         r+=a[i-1][i-1];
71     }
72     for(int i=1;i<=n;i++){
73         for(int j=1;j<=n;j++) scanf("%d",&b[i-1][j-1]);
74     }
75     for(int i=1;i<=n;i++) add_edge(ss,i,1,0);
76     for(int i=1;i<=n;i++) add_edge(n+i,tt,1,0);
77     while(r-l>eps){
78         db mid=(l+r)/2;
79         for(int i=0;i<n;i++)
80             for(int j=0;j<n;j++){
81                 cost[(i*n+j)<<1]=a[i][j]-mid*b[i][j];
82                 cost[(i*n+j)<<1|1]=-a[i][j]+mid*b[i][j];
83             }
84         db t=maxcostmaxflow();
85         if(t+eps>0) l=mid,ans=mid;
86         else r=mid;
87     }
88     printf("%.6lf",ans);
89 }

 

posted @ 2018-03-16 18:52  Cupcake  阅读(180)  评论(0编辑  收藏  举报