bzoj4819 [Sdoi2017]新生舞会 分数规划+最大费用最大流
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=4819
题解
首先上面说,
\]
要 \(C\) 最大。这是一种非常常见的分数规划模型,于是二分后转化成
\]
于是问题转化为求出权值和最大的方案满足每个人只选择一次。
可以是一个二分图匹配的模型,所以可以转化为最大费用最大流完成。
时间复杂度很玄学,不知道为什么能过。
调了半年的最小费用最大流突然想起来应该维护最大费用最大流。
#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]新生舞会 分数规划+最大费用最大流的更多相关文章
- [BZOJ4819][SDOI2017]新生舞会(分数规划+费用流,KM)
4819: [Sdoi2017]新生舞会 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1097 Solved: 566[Submit][Statu ...
- 【bzoj4819】[Sdoi2017]新生舞会 分数规划+费用流
题目描述 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个 ...
- 4819: [Sdoi2017]新生舞会 分数规划
题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4819 思路 分数规划的模板题?(好菜呀) 假如n=3吧(懒得写很长的式子) \(c=\fra ...
- P3705 [SDOI2017]新生舞会 分数规划 费用流
#include <algorithm> #include <iterator> #include <iostream> #include <cstring& ...
- bzoj 4819: [Sdoi2017]新生舞会【二分+最小费用最大流】
如果\( b[i]==0 \)那么就是裸的费用流/KM,当然KM快一些但是为什么不写KM呢因为我不会打板子了 考虑二分答案,那么问题变成了判定问题. \[ ans=\frac {a_1+a_2+... ...
- BZOJ4819 [Sdoi2017]新生舞会 【01分数规划 + 费用流】
题目 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人 ...
- BZOJ4819: [Sdoi2017]新生舞会(01分数规划)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1029 Solved: 528[Submit][Status][Discuss] Descripti ...
- bzoj4819 [Sdoi2017]新生舞会
Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的 ...
- 【BZOJ4819】[Sdoi2017]新生舞会 01分数规划+费用流
[BZOJ4819][Sdoi2017]新生舞会 Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女 ...
随机推荐
- Spring 由缓存切点驱动的通知者
Spring 缓存通知者和切点 缓存切点 /** * Spring 核心切点抽象 */ public interface Pointcut { /** * 类过滤器,当前切点是否需要织入在指定的类上 ...
- centOS7 flask项目布署
先用1张图表示centOS布署flask的关键点,以及可能遇到的问题,及解决办法. 图片看不清,可以[下载]下来看,清晰度能够看清字 [目标] 局域网内,通过url可以访问flask编写的api 更新 ...
- Linux_RHEV虚拟化_基础理论&KVM
目录 目录 RHEV KVM Full 完全虚拟化 PV半虚拟化 Full和PV最大的区别 HVMHardware Virtual Manager硬件辅助虚拟化 Setup KVM Use the v ...
- sql语句实现行转列的3种方法实例
sql语句实现行转列的3种方法实例 一般在做数据统计的时候会用到行转列,假如要统计学生的成绩,数据库里查询出来的会是这样的,但这并不能达到想要的效果,所以要在查询的时候做一下处理,下面话不多说了,来一 ...
- Cocos2d-X网络编程(4) Cocos2d中的网络通信协议——Socket通信
Socket,俗称网络套接字,本身并不是协议,而是一个调用接口,是对TCP/IP协议的封装和应用,.提供了一系列方法方便开发者进行网络通讯. TCP/IP协议是使用最早的通讯协议,它是传输层协议,主要 ...
- ubutnu同时安装OpenCV2和OpenCV3及contrib
1.OpenCV2源码安装 安装依赖项 sudo apt-get install build-essential //build-essential是c语言的开发包,包含了gcc make gdb和l ...
- 机器学习实战-Logistics回归
Logistics回归:实战,有两个特征X0,X1.100个样本,进行Logistics回归 1.导入数据 def load_data_set(): """ 加载数据集 ...
- 20191112 Spring Boot官方文档学习(4.3)
4.3.Profiles Spring Profiles提供了一种隔离部分应用程序配置并使之仅在某些环境中可用的方法.任何@Component,@Configuration或@Configuratio ...
- 第十四周总结&实验报告八
实验八 实现一个简单的记事本操作,有菜单项的 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; impo ...
- 最全的DevOps自动化工具集合
版本控制&协作开发:GitHub.GitLab.BitBucket.SubVersion.Coding.Bazaar 自动化构建和测试:Apache Ant.Maven .Selenium.P ...