BZOJ 3571 [Hnoi2014]画框(最小乘积完美匹配)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=3571
【题目大意】
给出一张二分图,每条边上有a,b两个值,求完美匹配,
使得suma*sumb最小。
【题解】
把方案看成一个二维点,x=sum(a),y=sum(b)
答案一定在下凸壳上,找到l,r两个点,l是x最小的,r是y最小的
然后递归调用work(l,r):找到离该直线最远的点,那个点一定在下凸壳上
将边权设为(a,b)叉积(l-r),求出最小完美匹配就是那个点mid
因为叉积计算的时候包含符号,(suma,sumb)与直线的叉积最小就是三角形的面积最大,
因而就是最远点,总和的叉积最小等价于叉积最小完美匹配。
然后递归work(l,mid),work(mid,r)
就能够枚举下凸壳上所有的点了。
【代码】
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=310;
const LL INF=0x3f3f3f3f3f3f3f3f;
int nx,ny; //两边的点数
LL g[N][N]; //二分图描述
int linker[N];//y中各点匹配状态
LL lx[N],ly[N];//x,y中的点标号
int n;
LL slack[N];
bool visx[N],visy[N];
LL ans=INF;
int T,a[N][N],b[N][N];
struct P{
int x,y;
P(){x=y=0;}
P(int _x,int _y){x=_x;y=_y;}
P operator-(const P&rhs){return P(x-rhs.x,y-rhs.y);}
}l,r;
LL cross(P a,P b){return (LL)a.x*b.y-(LL)a.y*b.x;}
bool DFS(int x){
visx[x]=1;
for(int y=0;y<ny;y++){
if(visy[y])continue;
int tmp=lx[x]+ly[y]-g[x][y];
if(tmp==0){
visy[y]=true;
if(linker[y]==-1||DFS(linker[y])){
linker[y]=x;
return 1;
}
}else if(slack[y]>tmp)slack[y]=tmp;
}return 0;
}
P KM(){
P p;
memset(linker,-1,sizeof(linker));
memset(ly,0,sizeof(ly));
for(int i=0;i<nx;i++){
lx[i]=-INF;
for(int j=0;j<ny;j++)if(g[i][j]>lx[i])lx[i]=g[i][j];
}
for(int x=0;x<nx;x++){
for(int i=0;i<ny;i++)slack[i]=INF;
for(;;){
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
if(DFS(x))break;
LL d=INF;
for(int i=0;i<ny;i++)if(!visy[i]&&d>slack[i])d=slack[i];
for(int i=0;i<nx;i++)if(visx[i])lx[i]-=d;
for(int i=0;i<ny;i++){
if(visy[i])ly[i]+=d;
else slack[i]-=d;
}
}
}LL res=0;
for(int i=0;i<ny;i++)if(linker[i]!=-1){
p.x+=a[linker[i]][i];
p.y+=b[linker[i]][i];
}res=(LL)p.x*p.y;
if(res<ans)ans=res;
return p;
}
void work(P l,P r){
P t=l-r;
for(int i=0;i<n;i++)for(int j=0;j<n;j++)g[i][j]=-cross(P(a[i][j],b[i][j]),t);
P mid=KM();
if(cross(mid-l,r-mid)>0)work(l,mid),work(mid,r);
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n); ans=INF;
for(int i=0;i<n;i++)for(int j=0;j<n;j++)scanf("%d",&a[i][j]);
for(int i=0;i<n;i++)for(int j=0;j<n;j++)scanf("%d",&b[i][j]);
nx=ny=n;
for(int i=0;i<n;i++)for(int j=0;j<n;j++)g[i][j]=-a[i][j]; l=KM();
for(int i=0;i<n;i++)for(int j=0;j<n;j++)g[i][j]=-b[i][j]; r=KM();
work(l,r);
printf("%lld\n",ans);
}return 0;
}
BZOJ 3571 [Hnoi2014]画框(最小乘积完美匹配)的更多相关文章
- bzoj3571: [Hnoi2014]画框 最小乘积匹配+最小乘积XX总结,
思路大概同bzoj2395(传送门:http://www.cnblogs.com/DUXT/p/5739864.html),还是将每一种匹配方案的Σai看成x,Σbi看成y,然后将每种方案转化为平面上 ...
- bzoj 3571: [Hnoi2014]画框
Description 小T准备在家里摆放几幅画,为此他买来了N幅画和N个画框.为了体现他的品味,小T希望能合理地搭配画与画框,使得其显得既不过于平庸也不太违和.对于第 幅画与第 个画框的配对,小T都 ...
- UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design
题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi ...
- POJ 2404 Jogging Trails(最小权完美匹配)
[题目链接] http://poj.org/problem?id=2404 [题目大意] 给出一张图,求走遍所有的路径至少一次,并且回到出发点所需要走的最短路程 [题解] 如果图中所有点为偶点,那么一 ...
- hdu1533 Going Home km算法解决最小权完美匹配
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...
- UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)
恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...
- uva 1411 Ants (权值和最小的完美匹配---KM算法)
uva 1411 Ants Description Young naturalist Bill studies ants in school. His ants feed on plant-louse ...
- 紫书 例题11-10 UVa 1349 (二分图最小权完美匹配)
二分图网络流做法 (1)最大基数匹配.源点到每一个X节点连一条容量为1的弧, 每一个Y节点连一条容量为1的弧, 然后每条有向 边连一条弧, 容量为1, 然后跑一遍最大流即可, 最大流即是最大匹配对数 ...
随机推荐
- Response.Redirect在新窗口打开(转载)
Response.Rederect在默认情况下是在本页跳转,所以除了在js中用window.open或是给A标签添加target属性之外,在后台似乎不能来打开新的页面,其实不然,通过设置form的ta ...
- Warning: File upload error - unable to create a temporary file in Unknown on line 0
upload_tmp_dir 临时文件夹问题 上传文件提示 Warning: File upload error - unable to create a temporary file in Unkn ...
- css文本垂直水平居中
一.单行文本居中 .content{ height:100px; line-height:100px; text-align:center; border:1px solid red; } 效果图 二 ...
- NOI2018游记&我的OI历程
day1 今天是报到日,坐着早上9点的飞机到了长沙,午饭时间到达雅礼洋湖. 宿舍还是一模一样,虽然是在女生宿舍. wifi信号还是一样的德行,刻意避开了宿舍内,只好把手机放在窗台上开热点. 饭菜还是如 ...
- 土司论坛nc反弹神器使用方法
说明: PS:我本机是linux,因为没有服务器所以使用win7来演示.倘若你是windows可以在本机生成dll以后再放到服务器上面去执行dll即可反弹shell物理机ip:192.168.1.12 ...
- 通用套接字选项和TCP套接字选项
1. 套接字选项函数原型: #include <sys/socket.h> int getsockopt(int sockfd, int level, int optname, void ...
- binlog2sql 回滚误操作
参考过在资料: https://github.com/wuyongshenghub/mysqlbinlog2sql https://www.cnblogs.com/xuanzhi201111/p/66 ...
- C#反射动态调用dll中的方法及使用QuartZ.net实现作业调度
using Quartz; using Quartz.Impl; using System; using System.Collections.Generic; using System.Linq; ...
- Python的语言特性
1.Python的函数传参 Python中所有的变量都可以理解为内存中一个对象的“引用”,或者,也可以看似C中的void *的感觉.这里记住的是类型是属于对象的,而不是变量.对象分为两种: 可更改的: ...
- f1 f12热键关闭
fn+f2进入bios系统——>找到configuration——>Hotkey Mode——>enter——>选择disable——>fn+f10保存