题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=4819

题解

首先上面说,

\[C = \frac{\sum\limits_{i=1}^n a'_i}{\sum\limits_{i=1}^n b'_i}
\]

要 \(C\) 最大。这是一种非常常见的分数规划模型,于是二分后转化成

\[\sum\limits_{i=1}^n a'_i - k \cdot b'_i \geq 0
\]

于是问题转化为求出权值和最大的方案满足每个人只选择一次。

可以是一个二分图匹配的模型,所以可以转化为最大费用最大流完成。


时间复杂度很玄学,不知道为什么能过。

调了半年的最小费用最大流突然想起来应该维护最大费用最大流。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int NN = 100 + 7;
const int N = 100 * 100 + 7;
const int M = 100 * 100 + 200 + 7;
const int INF = 0x3f3f3f3f; int n, nod, S, T, hd, tl;
int a[NN][NN], b[NN][NN], id[NN][NN], q[N], inq[N], cur[N], vis[N];
double dis[N]; struct Edge { int to, ne, f; double w; } g[M << 1]; int head[N], tot = 1;
inline void addedge(int x, int y, int z, double w) { g[++tot].to = y, g[tot].f = z, g[tot].w = w, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y, int f, double w) { addedge(x, y, f, w), addedge(y, x, 0, -w); } inline void qpush(int x) { ++tl; tl == N ? tl = 1 : 0; q[tl] = x; }
inline int qhead() { ++hd; hd == N ? hd = 1 : 0; return q[hd]; }
inline bool spfa() {
for (int i = 1; i <= nod; ++i) dis[i] = -1e9, vis[i] = 0, cur[i] = head[i];
q[hd = 0, tl = 1] = S, inq[S] = 0, dis[S] = 0;
while (hd != tl) {
int x = qhead();
inq[x] = 0;
for fec(i, x, y) if (g[i].f && smax(dis[y], dis[x] + g[i].w) && !inq[y]) qpush(y), inq[y] = 1;
}
return dis[T] > -1e9;
}
inline int dfs(int x, int a, double &mc) {
if (x == T || !a) return mc += dis[x] * a, a;
int f, flow = 0;
vis[x] = 1;
for (int &i = cur[x]; i; i = g[i].ne) {
int y = g[i].to
if (vis[y] || (dis[y] != dis[x] + g[i].w)) continue;
if (!(f = dfs(y, std::min(g[i].f, a), mc))) continue;
g[i].f -= f, g[i ^ 1].f += f;
flow += f, a -= f;
if (!a) return flow;
}
dis[x] = INF;
return flow;
}
inline double mcmf() {
double ans = 0, tmp = 0;
while (spfa()) tmp = 0, dfs(S, INF, tmp), ans += tmp;
return ans;
} inline bool check(double mid) {
memset(head, 0, sizeof(int) * (nod + 1)), tot = 1;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) adde(i, j + n, 1, a[i][j] - mid * b[i][j]);
for (int i = 1; i <= n; ++i) adde(S, i, 1, 0), adde(i + n, T, 1, 0);
return mcmf() >= 0;
} inline void work() {
S = ++nod, T = ++nod;
double l = 0, r = 1e4 + 7;
while (r - l >= 1e-7) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("%.6lf\n", l);
} inline void init() {
read(n);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) read(a[i][j]), id[i][j] = ++nod;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) read(b[i][j]);
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj4819 [Sdoi2017]新生舞会 分数规划+最大费用最大流的更多相关文章

  1. [BZOJ4819][SDOI2017]新生舞会(分数规划+费用流,KM)

    4819: [Sdoi2017]新生舞会 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1097  Solved: 566[Submit][Statu ...

  2. 【bzoj4819】[Sdoi2017]新生舞会 分数规划+费用流

    题目描述 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个 ...

  3. 4819: [Sdoi2017]新生舞会 分数规划

    题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4819 思路 分数规划的模板题?(好菜呀) 假如n=3吧(懒得写很长的式子) \(c=\fra ...

  4. P3705 [SDOI2017]新生舞会 分数规划 费用流

    #include <algorithm> #include <iterator> #include <iostream> #include <cstring& ...

  5. bzoj 4819: [Sdoi2017]新生舞会【二分+最小费用最大流】

    如果\( b[i]==0 \)那么就是裸的费用流/KM,当然KM快一些但是为什么不写KM呢因为我不会打板子了 考虑二分答案,那么问题变成了判定问题. \[ ans=\frac {a_1+a_2+... ...

  6. BZOJ4819 [Sdoi2017]新生舞会 【01分数规划 + 费用流】

    题目 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人 ...

  7. BZOJ4819: [Sdoi2017]新生舞会(01分数规划)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1029  Solved: 528[Submit][Status][Discuss] Descripti ...

  8. bzoj4819 [Sdoi2017]新生舞会

    Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的 ...

  9. 【BZOJ4819】[Sdoi2017]新生舞会 01分数规划+费用流

    [BZOJ4819][Sdoi2017]新生舞会 Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女 ...

随机推荐

  1. 使用virt-manager创建无盘工作站(基于nfs文件系统)

    首先需要做些准备工作: 1.安装xming及virt-manager, 安装过程网上很多,就不一一叙述了.安装完成后,使用putty登陆服务器,需要配置如下: connection -> SSH ...

  2. wpf datagrid tooltip

    <DataGridTemplateColumn Header="购方名称" Width="260" HeaderStyle="{StaticRe ...

  3. Java ——补充:构造方法 super()与构造方法 无参 有参构造方法 this()与构造方法

    参考文章: https://blog.csdn.net/qq_33322074/article/details/86030836 https://blog.csdn.net/HD243608836/a ...

  4. 【HANA系列】SAP HANA SQL获取当前月的第一天

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL获取当前 ...

  5. LeetCode算法题-Shortest Distance to a Character(Java实现)

    这是悦乐书的第321次更新,第343篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第191题(顺位题号是821).给定字符串S和字符C,返回一个整数数组,表示字符串中所有 ...

  6. django 的 三个 时间 字段

  7. 初涉Java

    一.学习内容总结 1.程序入口 但如果类的定义使用了public class声明,那么文件名必须与类名保持一致,使用了class定义的类,文件名称可以和类名称不同. 2.输出语句 3.print与pr ...

  8. 004 gcc 编译 C/C++ 默认使用哪个标准

    0. 前言 我挺久没碰 C,不想就这么忘了,最近重温了一些相关知识 1. C 语言的几种"方言" 简单地说,有这么几种常见的 年份 名称 1983 ANSI C 1987 C87 ...

  9. 8. golang 基本类型转换

    golang 类型转换只能显性转换 不能自动转换 基本数据类型间的转换 var x1 int = 2 var x2 int16 var x3 int8 x2 = 200 + x1 x3 = 200 + ...

  10. 常用php算法

       一.冒泡排序function bubble($array){ $cnt = count($array); if($cnt <= 0) return $array; for($i =1;$i ...