分数规划模板题 , 会写就能A
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 105 << 1 , Mod = 998244353 , G = 3 , INF = 0x3f3f3f3f;
double PI = acos(-1) , eps = 1e-7;
struct Virt{
double x , y;
Virt(double _x = 0.0 , double _y = 0.0):x(_x) , y(_y){}
};
Virt operator + (Virt x , Virt y){return Virt(x.x + y.x , x.y + y.y);}
Virt operator - (Virt x , Virt y){return Virt(x.x - y.x , x.y - y.y);}
Virt operator * (Virt x , Virt y){return Virt(x.x * y.x - x.y * y.y , x.x * y.y + x.y * y.x);}
int read(){
int x = 0 , f = 1; char ch = getchar();
while(ch < ‘0‘ || ch > ‘9‘){if(ch == ‘-‘) f = -1 ; ch = getchar();}
while(ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘; ch = getchar();}
return x * f;
}
struct edge{
int pos , nx , cap;
double cost;
}e[(N * N) << 1];
int n , num , a[N][N] , b[N][N] , head[N];
void add(int u , int v , int c , double w){
e[++num].pos = v; e[num].cap = c; e[num].cost = w; e[num].nx = head[u]; head[u] = num;
e[++num].pos = u; e[num].cap = 0; e[num].cost = -w; e[num].nx = head[v]; head[v] = num;
}
struct mcfx{
double d[N];
int s , t , pre[N];
bool inq[N];
bool SPFA(){
memset(pre , 0 , sizeof(pre));
for(int i = 1 ; i <= t ; i++) d[i] = -1.0;
queue<int> q;
d[s] = 0.0 , q.push(s);
while(!q.empty()){
int now = q.front(); q.pop(); inq[now] = false;
for(int i = head[now] ; i ; i = e[i].nx){
if(e[i].cap > 0 && d[e[i].pos] < d[now] + e[i].cost){
d[e[i].pos] = d[now] + e[i].cost;
pre[e[i].pos] = i;
if(!inq[e[i].pos]){
inq[e[i].pos] = true;
q.push(e[i].pos);
}
}
}
}
return d[t] != -1.0;
}
double Calc(){
int flow;
double ans = 0;
while(SPFA()){
flow = INF;
for(int i = t ; i != s ; i = e[pre[i] ^ 1].pos) flow = min(flow , e[pre[i]].cap);
for(int i = t ; i != s ; i = e[pre[i] ^ 1].pos) e[pre[i]].cap -= flow , e[pre[i] ^ 1].cap += flow;
ans += d[t] * flow;
}
return ans;
}
void init(double mid){
num = 1;
memset(head , 0 , sizeof(head));
for(int i = 1 ; i <= n ; i++)
add(s , i , 1 , 0) , add(i + n , t , 1 , 0);
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= n ; j++)
add(i , j + n , 1 , (double)a[i][j] - mid * b[i][j]);
}
}netflow;
int main(){
scanf("%d",&n);
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= n ; j++)
scanf("%d",&a[i][j]);
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= n ; j++)
scanf("%d",&b[i][j]);
double l = 0.0 , r = 1000005.0 , ans;
netflow.s = n * 2 + 1 , netflow.t = n * 2 + 2;
while(abs(r - l) > eps){
double mid = (r + l) * 0.5;
netflow.init(mid);
if(netflow.Calc() > eps) ans = mid , l = mid + eps;
else r = mid - eps;
}
printf("%lf",ans);
return 0;
}