[BZOJ4819][SDOI2017]新生舞会(分数规划+费用流,KM)
4819: [Sdoi2017]新生舞会
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1097 Solved: 566
[Submit][Status][Discuss]Description
学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴。有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴。Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度。Cathy还需要考虑两个人一起跳舞是否方便,比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度。当然,还需要考虑很多其他问题。Cathy想先用一个程序通过a[i][j]和b[i][j]求出一种方案,再手动对方案进行微调。Cathy找到你,希望你帮她写那个程序。一个方案中有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^4Output
一行一个数,表示C的最大值。四舍五入保留6位小数,选手输出的小数需要与标准输出相等Sample Input
3
19 17 16
25 24 23
35 36 31
9 5 6
3 4 2
7 8 9Sample Output
5.357143HINT
Source
有点太裸了,两个算法都非常明显。
”根据答案的式子可以确定是分数规划,根据题目名称‘舞会’可以确定是二分图匹配”然后这题就做完了。
先知道是KM,然后看网上写的都是网络流然后也开始写网络流,写了半天发现是费用流。。
费用流方面并不是普通的最大费用流,因为最后必须全部匹配,所以直接把SPFA成功的条件从一般最大费用流的"dis[T]>0"改成"dis[T]!=-inf"就好了。
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=,M=,inf=;
const double eps=1e-;
double ans,c[M],dis[N];
int n,cnt,mn,S,T,f[M],to[M],nxt[M],q[M],pre[N],inq[N],h[N],a[N][N],b[N][N];
void add(int u,int v,int w,double co){
to[++cnt]=v; f[cnt]=w; c[cnt]=co; nxt[cnt]=h[u]; h[u]=cnt;
to[++cnt]=u; f[cnt]=; c[cnt]=-co; nxt[cnt]=h[v]; h[v]=cnt;
} bool spfa(){
rep(i,,T) pre[i]=-,inq[i]=,dis[i]=-inf;
dis[S]=; q[]=S;
for (int st=,ed=; st<ed; ){
int x=q[++st]; inq[x]=;
For(i,x) if (f[i] && dis[k=to[i]]<dis[x]+c[i]){
dis[k]=dis[x]+c[i]; pre[k]=i;
if (!inq[k]) inq[k]=,q[++ed]=k;
}
}
return dis[T]!=dis[];
} void work(){
for (ans=; spfa(); ans+=dis[T]*mn){
mn=inf;
for (int i=pre[T]; ~i; i=pre[to[i^]]) mn=min(mn,f[i]);
for (int i=pre[T]; ~i; i=pre[to[i^]]) f[i]-=mn,f[i^]+=mn;
}
} int main(){
freopen("ball.in","r",stdin);
freopen("ball.out","w",stdout);
scanf("%d",&n);
rep(i,,n) rep(j,,n) scanf("%d",&a[i][j]);
rep(i,,n) rep(j,,n) scanf("%d",&b[i][j]);
double L=,R=; S=n*+,T=n*+;
while (L+eps<R){
double mid=(L+R)/; ans=;
rep(i,,*n+) h[i]=; cnt=;
rep(i,,n) add(S,i,,);
rep(i,,n) add(i+n,T,,);
rep(i,,n) rep(j,,n) add(i,j+n,,a[i][j]-mid*b[i][j]);
work(); if (ans>eps) L=mid; else R=mid;
}
printf("%.6lf\n",L);
return ;
}
KM就没什么好说的了,速度快5倍。果然不能依靠玄学,当然这题的图比较稠密也是原因之一。
原来KM也可以跑负权图。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=,inf=;
const double eps=1e-;
int n,lk[N],vx[N],vy[N],a[N][N],b[N][N];
double lx[N],ly[N],w[N][N],s[N];
double abs(double x){ return (x<)?-x:x; } bool dfs(int x){
vx[x]=;
rep(y,,n) if (!vy[y]){
double t=lx[x]+ly[y]-w[x][y];
if (abs(t)<eps){
vy[y]=;
if (lk[y]==- || dfs(lk[y])) { lk[y]=x; return ; }
}else s[y]=min(s[y],t);
}
return ;
} double KM(){
rep(i,,n) lx[i]=-inf,ly[i]=,lk[i]=-;
rep(i,,n) rep(j,,n) lx[i]=max(lx[i],w[i][j]);
rep(x,,n){
rep(i,,n) s[i]=inf;
while (){
memset(vx,,sizeof(vx));
memset(vy,,sizeof(vy));
if (dfs(x)) break;
double d=inf;
rep(i,,n) if (!vy[i]) d=min(d,s[i]);
rep(i,,n) if (vx[i]) lx[i]-=d;
rep(i,,n) if (vy[i]) ly[i]+=d; else s[i]-=d;
}
}
double res=;
rep(i,,n) res+=w[lk[i]][i];
return res;
} int main(){
freopen("ball.in","r",stdin);
freopen("ball.out","w",stdout);
scanf("%d",&n);
rep(i,,n) rep(j,,n) scanf("%d",&a[i][j]);
rep(i,,n) rep(j,,n) scanf("%d",&b[i][j]);
double L=,R=;
while (L+eps<R){
double mid=(L+R)/;
rep(i,,n) rep(j,,n) w[i][j]=a[i][j]-mid*b[i][j];
if (KM()>eps) L=mid; else R=mid;
}
printf("%.6lf\n",L);
return ;
}
[BZOJ4819][SDOI2017]新生舞会(分数规划+费用流,KM)的更多相关文章
- 【bzoj4819】[Sdoi2017]新生舞会 分数规划+费用流
题目描述 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个 ...
- P3705 [SDOI2017]新生舞会 分数规划 费用流
#include <algorithm> #include <iterator> #include <iostream> #include <cstring& ...
- bzoj4819 [Sdoi2017]新生舞会 分数规划+最大费用最大流
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4819 题解 首先上面说, \[ C = \frac{\sum\limits_{i=1}^n a ...
- 4819: [Sdoi2017]新生舞会 分数规划
题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4819 思路 分数规划的模板题?(好菜呀) 假如n=3吧(懒得写很长的式子) \(c=\fra ...
- BZOJ_4819_[Sdoi2017]新生舞会_01分数规划+费用流
BZOJ_4819_[Sdoi2017]新生舞会_01分数规划+费用流 Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞 ...
- bzoj4819 [Sdoi2017]新生舞会
Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的 ...
- 【BZOJ4819】[Sdoi2017]新生舞会 01分数规划+费用流
[BZOJ4819][Sdoi2017]新生舞会 Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女 ...
- BZOJ4819 [Sdoi2017]新生舞会 【01分数规划 + 费用流】
题目 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人 ...
- P3705 [SDOI2017]新生舞会 01分数规划+费用流
$ \color{#0066ff}{ 题目描述 }$ 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴. 有\(n\)个男生和\(n\)个女生参加舞会买一个男生和一个女生一 ...
随机推荐
- JS之document例题讲解1(两张表之间数据转移、日期时间选择、子菜单下拉、用div做下拉菜单、事件总结)
作业一:两个列表之间数据从一个列表移动到另一个列表 <div style="width:600px; height:500px; margin-top:20px"> & ...
- iOS多线程
iOS开发Demo(示例程序)源代码
本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址(2013年12月29日更新版) iOS程序源代码下载链接:01.大任务.zip22 ...
- 联系博主 Contact
李莫 / Ray OI 蒟蒻一只 / A Player of Olympiad in Informatics QQ:740929894 邮箱 / Email :rayking2017@outlook. ...
- select下拉箭头改变,兼容ie8/9
各个浏览器下select默认的下拉箭头差别较大,通常会清除默认样式,重新设计 <html> <head> <meta charset="utf-8"& ...
- 区块链~Merkle Tree(默克尔树)算法解析~转载
转载~Merkle Tree(默克尔树)算法解析 /*最近在看Ethereum,其中一个重要的概念是Merkle Tree,以前从来没有听说过,所以查了些资料,学习了Merkle Tree的知识,因为 ...
- Java基础 变量和数据类型及相关操作
Java基本语法: 1):Java语言严格区分大小写,好比main和Main是完全不同的概念. 2):一个Java源文件里可以定义多个Java类,但其中最多只能有一个类被定义成public类.若源文件 ...
- Linux中查看进程占用内存的情况【转】
转自:http://hutaow.com/blog/2014/08/28/display-process-memory-in-linux/ Linux中查看某个进程占用内存的情况,执行如下命令即可,将 ...
- 安全测试===burpsuit指南
网址: https://www.gitbook.com/book/t0data/burpsuite/details 引子 刚接触web安全的时候,非常想找到一款集成型的渗透测试工具,找来找去,最终选择 ...
- ogre3d环境配置 SDK安装配置及简单事例教程
ogre3d环境配置 SDK安装配置及简单事例教程 http://www.cr173.com/html/22594_1.html ogre3d环境配置 SDK安装配置及简单事例教程 http://ww ...
- win10出现"win10系统即将过期,请激活"的处理办法
当打开电脑时,出现"你的win10系统即将过期,请前往激活”的提示.上网查了解决方案,避免以后在出现这样的情况,现将解决步骤整理如下: 1.下载KMSpico激活软件,百度网盘下载链接如下: ...