「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 }