BZOJ4819: [Sdoi2017]新生舞会(01分数规划)
Description
学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴。有n个男生和n个女生参加舞会
买一个男生和一个女生一起跳舞,互为舞伴。Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出
a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度。Cathy还需要考虑两个人一起跳舞是否方便,
比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度。当然,
还需要考虑很多其他问题。Cathy想先用一个程序通过a[i][j]和b[i][j]求出一种方案,再手动对方案进行微调。C
athy找到你,希望你帮她写那个程序。一个方案中有n对舞伴,假设没对舞伴的喜悦程度分别是a'1,a'2,...,a'n,
假设每对舞伴的不协调程度分别是b'1,b'2,...,b'n。令
C=(a'1+a'2+...+a'n)/(b'1+b'2+...+b'n),Cathy希望C值最大。
Input
第一行一个整数n。
接下来n行,每行n个整数,第i行第j个数表示a[i][j]。
接下来n行,每行n个整数,第i行第j个数表示b[i][j]。
1<=n<=100,1<=a[i][j],b[i][j]<=10^4
Output
一行一个数,表示C的最大值。四舍五入保留6位小数,选手输出的小数需要与标准输出相等
Sample Input
3 19 17 16 25 24 23 35 36 31 9 5 6 3 4 2 7 8 9
Sample Output
5.357143
HINT
Source
鸣谢infinityedge上传
洛谷居然卡邻接表,丧心病狂
思路比较简单,裸的洞妖分数规划
枚举一个ans
然后从S向男生连一条流量为1,费用为0的边
从每个女生向T连一条流量为1,费用为0的边
从每个女生向每个男生连一条流量为1,费用为a[i][j]-ans*b[i][j]的边
二分检验
注意边的编号必须从0开始。
注意精度
// luogu-judger-enable-o2
#include<cstdio>
#include<queue>
#include<cstring>
#include<cstdlib>
#define INF 1e8+10
using namespace std;
const int MAXN=201;
const double eps=1e-7;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++)
char buf[1<<20],*p1=buf,*p2=buf;
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct node
{
int u,v,f,nxt;
double w;
}edge[MAXN*MAXN];
int head[MAXN],num=0;
int N,S,T;
int a[233][233],b[233][233];
double ans=0.0;
inline void add_edge(int x,int y,int z,double k)
{
edge[num].u=x;
edge[num].v=y;
edge[num].f=z;
edge[num].w=k;
edge[num].nxt=head[x];
head[x]=num++;
}
inline void AddEdge(int x,int y,int z,double k)
{
add_edge(x,y,z,k);
add_edge(y,x,0,-k);
}
int arrive[MAXN],vis[MAXN],pre[MAXN];
double dis[MAXN];
bool SPFA()
{
queue<int>q;
q.push(S);
for(register int i=S;i<=T;i++) dis[i]=-1e20,arrive[i]=0;
memset(vis,0,sizeof(vis));
dis[S]=0;vis[S]=1;
while(q.size()!=0)
{
int p=q.front();q.pop();
vis[p]=0;arrive[p]=1;
for(int i=head[p];i!=-1;i=edge[i].nxt)
{
if(edge[i].f&&dis[edge[i].v]<dis[p]+edge[i].w)
{
dis[edge[i].v]=dis[p]+edge[i].w;
pre[edge[i].v]=i;
if(!vis[edge[i].v])
q.push(edge[i].v),vis[edge[i].v]=1;
}
}
}
return arrive[T];
}
int dfs()
{
int mn=INF;
int now=T;
while(pre[now])
{
mn=min(mn,edge[pre[now]].f);
now=edge[pre[now]].u;
}
ans+=mn*dis[T];
now=T;
while(pre[now])
{
edge[pre[now]].f-=mn;
edge[pre[now]^1].f+=mn;
now=edge[pre[now]].u;
}
}
bool check(double val)
{
memset(pre,0,sizeof(pre));
memset(head,-1,sizeof(head));
num=2;
for(int i=1;i<=N;i++) AddEdge(S,i,1,0);
for(int i=1;i<=N;i++) AddEdge(i+N,T,1,0);
for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) AddEdge(i,j+N,1,a[i][j]-1.0*val*b[i][j]);
ans=0.0;
while(SPFA())
dfs();
if (ans<=0) return 1;
else return 0;
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
//freopen("c.out","w",stdout);
#else
#endif
N=read();
S=0,T=N*2|1;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
a[i][j]=read();
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
b[i][j]=read();
double l=0,r=10000;
while(r-l>=eps)
{
double mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.6lf",l);
return 0;
}
- Java数组赋值
- 10.12 firewalld和netfilter
- 10.11 Linux网络相关
- 利用Crypto++实现RSA加密算法
- 重学javascript 红皮高程(6)
- WriteUp分享 | LCTF的一道preg_match绕过+出题人的锅
- 利用crypto++库实现AES加密算法
- Android之倒计时CountdownTimer用法
- WriteUp分享 | LCTF的一道padding oracle攻击+sprintf格式化字符串导致的SQL注入
- 10.27 target介绍
- Android 之游戏开发流程
- shell脚本后台运行
- Android的.so文件你需要知道那些知识
- xshel配色方案
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- s3cmd ls之迷惑
- 构建pyflink镜像
- apt-get update遇到NO_PUBKEY
- 遇到mpi worker exited on signal 9
- 容器共享GPU时查看容器使用的GPU编号
- oci runtime error: exec failed: container_linux.go:247: starting container process caused “exec: “/
- R|UpSet-集合可视化
- 美国队长的盾(一) 同心圆
- R|clusterProfiler-富集分析
- R|fastqcr QC数据处理
- R|timeROC-分析
- R|ML_code-线性回归(2)
- R|机器学习入门-多元线性回归(3)
- Bioinfo|bedtools-操作VCF文件
- 美国队长的盾(二)五角星