题目链接

戳我

\(Describe\)

有一场舞会,n个男生,n个女生,要组成n对舞伴,男生i和女生j组队的适合度是\(a_{ij}\),

不适合度是\(b_{ij}\),

让你求\(max(\sum(适合度)/\sum(不适合度))\)

\(Solution\)

这道题是\(01\)分数规划的好题目。我们首先拆分这个式子:

令\(A_i\)为舞伴的适合度,\(B_i\)为不适合度

\[C=\sum_{i=1}^{i<=n}a_i/\sum_{i=1}^{i<=n}b_i
\]

\[\sum_{i=1}^{i<=n}a_i=\sum_{i=1}^{i<=n}b_i*C
\]

\[\sum_{i=1}^{i<=n}a_i-\sum_{i=1}^{i<=n}b_i*C=0
\]

则我们可以对C二分一个数\(mid\)

\[令:ans=max(\sum_{i=1}^{i<=n}a_i-\sum_{i=1}^{i<=n}b_i*mid)
\]

如果\(ans>0\)则\(ans\)比\(C\)要小,反之比\(C\)大

那么这个\(max(ans)怎么求呢?\)

这个随便用个费用流搞一搞就好了;

  • 把每个人拆成\(x\)和\(x'\)
  • 将\(S\)和\(x\)相连,流量为1,费用为0
  • 将\(x'\)和\(T\)相连,流量为1,费用为0
  • 对于两个人\(x,y\)我们将\(x\)和\(y'\)相连,流量为1,费用为\(a[x][y]-mid*b[x][y]\)(因为我的spfa是跑的最短路,所以我写的是-a[x][y]+mid*b[x][y],最后跑出来的答案的绝对值就是最大费用最大流);
  • 跑一遍最大费用最大流

\(Code\)

#include<bits/stdc++.h>
using namespace std;
const double inf=1e9+7;
typedef long long ll;
int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9')
x=x*10+c-'0',c=getchar();
return x*f;
}
struct node{
int to,next,v;
double w;
}a[1000001];
int f[10001],pre[10001],fa[10001],s,t=1000,head[10001],cnt;
double dis[10001];
void add(int x,int y,int c,double v){
a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,a[cnt].w=v,head[x]=cnt;
a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,a[cnt].w=-v,head[y]=cnt;
}
queue<int>q;
int spfa(){
q.push(s);
for(int i=s;i<=t;i++)
dis[i]=inf;
memset(f,0,sizeof(f));
f[s]=1,dis[s]=0;
while(!q.empty()){
int now=q.front();
q.pop();
f[now]=0;
for(int i=head[now];i;i=a[i].next){
int v=a[i].to;
if(dis[v]>dis[now]+a[i].w&&a[i].v){
dis[v]=dis[now]+a[i].w,pre[v]=i,fa[v]=now;
if(!f[v])
f[v]=1,q.push(v);
}
}
}
if(dis[t]!=inf)
return 1;
return 0;
}
double ans1,ans;
void anser(){
ans=0,ans1=0;
while(spfa()){
int minx=2147483647;
for(int i=t;i!=s;i=fa[i])
minx=min(minx,a[pre[i]].v);
ans+=minx,ans1+=dis[t]*minx;
for(int i=t;i!=s;i=fa[i])
a[pre[i]].v-=minx,(pre[i]%2)?a[pre[i]+1].v+=minx:a[pre[i]-1].v+=minx;
}
}
double A[1001][1001],B[1001][1001];
int n;
bool check(double x){
memset(head,0,sizeof(head)),cnt=0;
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,-A[i][j]+x*B[i][j]);
}
anser();
return (-ans1)>=0;
}
int main(){
n=read();
double l=0,r=10000,maxx=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>A[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>B[i][j];
while(r-l>=1e-7){
double mid=(l+r)*0.5;
if(check(mid))
l=mid,maxx=max(maxx,mid);
else r=mid;
}
printf("%0.6lf",maxx);
}

「SDOI2017」新生舞会的更多相关文章

  1. LibreOJ 2003. 「SDOI2017」新生舞会 基础01分数规划 最大权匹配

    #2003. 「SDOI2017」新生舞会 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  2. LibreOJ #2003. 「SDOI2017」新生舞会

    内存限制:256 MiB 时间限制:1500 ms 标准输入输出 题目类型:传统 评测方式:文本比较 上传者: 匿名 01分数规划(并不知道这是啥..) km或费用流(并不会)验证 屠龙宝刀点击就送 ...

  3. loj2003 「SDOI2017」新生舞会

    分数规划+KM 算法 这个KM不好,看算法竞赛进阶指南的 #include <iostream> #include <cstring> #include <cstdio& ...

  4. 「SDOI2017」树点涂色 解题报告

    「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...

  5. AC日记——「SDOI2017」序列计数 LibreOJ 2002

    「SDOI2017」序列计数 思路: 矩阵快速幂: 代码: #include <bits/stdc++.h> using namespace std; #define mod 201704 ...

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

    新生舞会 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 学校组织了一次新生舞会,Cathy ...

  7. Unique -「企划」新生守则(?

    随想随记,主要是整活. 红色贝雷帽大爷会在校园不定期游走,遇见记得打招呼. 面食堂冰沙类饮品请快速解决或者边喝边搅,如果发现饮品甜度骤减请快速前往最近的垃圾桶扔掉. 关于散养猫小黄和小黑. 如果看见小 ...

  8. 【LOJ 2004】「SDOI2017」硬币游戏

    LOJ 2004 100pts 首先我们肯定要建AC自动机的.. 那么这题就肯定是个AC自动机上\(dp\). 所以想想状态. 首先如果我们把状态设成这样行不行: \(dp(i)\)表示匹配到了i节点 ...

  9. loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)

    题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i ...

随机推荐

  1. SQLSERVER 2008 查询数据字段名类型

    SELECT * FROM Master..SysDatabases ORDER BY Name SELECT Name,* FROM Master..SysDatabases where Name= ...

  2. Oracle常见的表连接的方法

    1 排序合并连接SMJ Sort merge join 排序合并总结: 1 通常情况下,排序合并连接的效率远不如hash join,前者适用范围更广,hj只使用于等值连接,smj范围更广(<,& ...

  3. python开发mysql:mysql安装(windows)&密码找回&存储引擎简介&库表的增删改查

    一,mysql安装 下载地址 https://dev.mysql.com/downloads/file/?id=471342 解压后,将目录C:\mysql-5.7.19-winx64\bin添加到计 ...

  4. spring mvc helloworld 和表单功能、页面重定向

    Spring MVC Hello World 例子 这里有个很好的教程:https://www.cnblogs.com/wormday/p/8435617.html 下面的例子说明了如何使用 Spri ...

  5. 缓存 memcached 与 redis

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  6. IDA Pro 权威指南学习笔记(六) - 次要的 IDA 显示窗口

    十六进制窗口 IDA 十六进制窗口可以配置为显示各种格式,并可作为十六进制编辑器使用 默认情况下,十六进制窗口显示程序内容和列表的标准十六进制代码,每行显示 16 个字节,以及其对应的 ASCII 字 ...

  7. Python Twisted系列教程12:改进诗歌下载服务器

    作者:dave@http://krondo.com/a-poetry-transformation-server/  译者:杨晓伟(采用意译) 你可以从这里从头阅读这个系列. 新的服务器实现 这里我们 ...

  8. 免Oracle客户端程序监听程序配置

    Oracle默认安装时,监听程序和tnsnames程序中的监听方式都是默认的localhost,但免客户端的程序是连接不上的.这时需要: 1.将listener中的(HOST = localhost) ...

  9. Android 4 学习(12):Linkify & Broadcast event

    参考<Professional Android 4 Development> Linkify Linkfy类可以在Text View中创建超链接.匹配LInkify中正则表达式的文本将被L ...

  10. hadoop本地调试方法

    Mapreduce 是Hadoop上一个进行分布式数据运算和统计的框架,但是每次运行程序的时候都需要将程序打包并上传的集群环境中运行,这就会让程序的调试变得十分不方便.所以在这里写下这篇博客和大家交流 ...