#9 //[SDOI2017]新生舞会
题解:
分数规划+费用流
常数巨大开o2加inline加register还是不行
我也不知道为什么
代码:
#include <bits/stdc++.h> using namespace std; const int N=5e4; const int N1=2e3; #define INF 1e9 #define INF2 1e4 #define eps 1e-7 #define rg register #define IL inline int pre[N],aa[N],s,t,n,m; double dis[N]; bool vis[300]; int l,p1[N1][N1],p2[N1][N1],head[10000]; struct re{ int a,b,c,flow,from; double cost; }a[N]; IL void arr(int x,int y,int z,int flow,double cost) { a[++l].a=head[x]; a[l].b=y; a[l].c=z; a[l].flow=flow; a[l].from=x; a[l].cost=cost; head[x]=l; } IL bool bellmanford(double &flow,double &cost) { queue<int>q; for (rg int i=1;i<=t;i++) dis[i]=INF; aa[s]=INF; memset(vis,1,sizeof(vis)); q.push(s); while (!q.empty()) { rg int x=q.front(); q.pop(); rg int u=head[x]; while (u) { rg int v=a[u].b; if (dis[x]+a[u].cost<dis[v]&&a[u].c>a[u].flow) { dis[v]=dis[x]+a[u].cost; aa[v]=min(aa[x],a[u].c-a[u].flow); pre[v]=u; if (vis[v]) { vis[v]=0; q.push(v); } } u=a[u].a; } vis[x]=1; } if (dis[t]==INF) return(0); rg int x=t; flow+=aa[t]; cost+=aa[t]*dis[t]; while (pre[x]) { rg int y=pre[x]; a[y].flow+=aa[t]; if (y%2==1) a[y+1].flow-=aa[t]; else a[y-1].flow-=aa[t]; x=a[y].from; } return 1; } double flow,cost; IL void mincost() { while (bellmanford(flow,cost)); } #define mid (h+t)/2 IL bool check(double x) { l=0; memset(head,0,sizeof(head)); for (rg int i=1;i<=n;i++) for (rg int j=1;j<=n;j++) { arr(i,j+n,1,0,-(p1[i][j]-p2[i][j]*x)); arr(j+n,i,0,0,(p1[i][j]-p2[i][j]*x)); } s=0,t=2*n+1; for (rg int i=1;i<=n;i++) { arr(0,i,1,0,0); arr(i,0,0,0,0); arr(i+n,t,1,0,0); arr(t,i+n,0,0,0); } flow=0; cost=0; mincost(); if (cost<=0) return(1); else return(0); } int main() { std::ios::sync_with_stdio(false); cin>>n; for (rg int i=1;i<=n;i++) for (rg int j=1;j<=n;j++) cin>>p1[i][j]; for (rg int i=1;i<=n;i++) for (rg int j=1;j<=n;j++) cin>>p2[i][j]; double h=0,t=INF2; while (t-h>eps) { if (check(mid)) h=mid; else t=mid; } printf("%.6f",h); return 0; }