[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=4819
[算法]
很明显的0 / 1分数规划问题
首先二分答案 , 显然 , 若 sigma(Aij - mid * Bij) >= 0 , 说明有比mid更优的解
用费用流 / KM算法检验即可
时间复杂度 : O(N^3logN)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 110 const double inf = 1e15; const double EPS = 1e-9; int n; double delta; int match[MAXN]; int a[MAXN][MAXN] , b[MAXN][MAXN]; double la[MAXN] , lb[MAXN]; double c[MAXN][MAXN]; bool visiteda[MAXN] , visitedb[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline bool dfs(int u) { visiteda[u] = true; for (int i = 1; i <= n; i++) { if (!visitedb[i]) { if (fabs(la[u] + lb[i] - c[u][i]) < EPS) { visitedb[i] = true; if (!match[i] || dfs(match[i])) { match[i] = u; return true; } } else chkmin(delta , la[u] + lb[i] - c[u][i]); } } return false; } inline double KM() { for (int i = 1; i <= n; i++) { la[i] = -inf; lb[i] = 0; match[i] = 0; for (int j = 1; j <= n; j++) chkmax(la[i] , c[i][j]); } for (int i = 1; i <= n; i++) { while (true) { delta = inf; for (int j = 1; j <= n; j++) visiteda[j] = visitedb[j] = false; if (dfs(i)) break; for (int j = 1; j <= n; j++) { if (visiteda[j]) la[j] -= delta; if (visitedb[j]) lb[j] += delta; } } } double ret = 0; for (int i = 1; i <= n; i++) ret += c[match[i]][i]; return ret; } inline bool check(double mid) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { c[i][j] = 1.0 * a[i][j] - 1.0 * b[i][j] * mid; } } if (KM() >= 0) return true; else return false; } int main() { read(n); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { read(a[i][j]); } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { read(b[i][j]); } } double l = 0 , r = (int)1e4 , ans = 0; while (l + EPS < r) { double mid = (l + r) / 2.0; if (check(mid)) { ans = mid; l = mid; } else r = mid; } printf("%.6lf " , ans); return 0; }