思路大概同bzoj2395(传送门:http://www.cnblogs.com/DUXT/p/5739864.html),还是将每一种匹配方案的Σai看成x,Σbi看成y,然后将每种方案转化为平面上的点,再用km去找最远的点就行了。

然而几个月前就学过km且到现在还未写过一道km的题的我并不知道km如何对于负权给出最优解。。。。

#define XX 某传统算法(例如:最小生成树,二分图最优带权匹配什么的)

顺便总结一下最小乘积XX

即对于XX引入两个权值的概念(或是多个权值,一般是两个),看似无从下手,却可以将每一组可行解的方案的两个sum转化为平面内一个点,然后就可以发现一个十分优美的性质即最优解一定在凸包上,于是可以利用一种类似于快包算法的算法,依旧是用XX找出一定在凸包上的两个点,然后再次利用XX进行分治,递归地下去找,弄清楚边界条件(一般一个叉乘就可以轻松搞定),这样问题就被轻易地解决了。(貌似知道了这样的一个模板,基本所有类似问题都可以得到解决)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 100
#define inf 100000000 int cases,n;
int a[maxn][maxn],b[maxn][maxn],val[maxn][maxn],slack[maxn],valx[maxn],valy[maxn],linky[maxn];
bool visx[maxn],visy[maxn]; struct point{
int x,y;
}ans; point operator -(point a,point b){return(point){a.x-b.x,a.y-b.y};}
double operator *(point a,point b){return a.x*b.y-a.y*b.x;} bool find(int x){
visx[x]=;
for (int y=;y<=n;y++)
if (!visy[y]){
int t=valx[x]+valy[y]-val[x][y];
if (!t){
visy[y]=;
if (!linky[y]||find(linky[y])){
linky[y]=x;
return ;
}
}
else slack[y]=min(slack[y],t);
}
return ;
} point km(){
memset(valx,,sizeof(valx));
memset(valy,,sizeof(valy));
memset(linky,,sizeof(linky));
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
valx[i]=max(valx[i],val[i][j]);
for (int x=;x<=n;x++){
memset(slack,,sizeof(slack));
while (){
memset(visx,,sizeof(visx));
memset(visy,,sizeof(visy));
if (find(x)) break;
int d=inf;
for (int i=;i<=n;i++) if (!visy[i]) d=min(d,slack[i]);
for (int i=;i<=n;i++) if (visx[i]) valx[i]-=d;
for (int i=;i<=n;i++) if (visy[i]) valy[i]+=d;
}
}
point now={,};
for (int i=;i<=n;i++) now.x+=a[linky[i]][i],now.y+=b[linky[i]][i];
if ((ans.x==inf&&ans.y==inf)||(ans.x*ans.y>now.x*now.y)) ans=now;
return now;
} bool operator ==(point a,point b){return a.x==b.x&&a.y==b.y;} void solve(point x,point y){
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
val[i][j]=b[i][j]*(x.x-y.x)+a[i][j]*(y.y-x.y);
point z=km();
if ((z-x)*(y-z)<=) return;
solve(x,z);
solve(z,y);
} int main(){
scanf("%d",&cases);
while (cases--){
scanf("%d",&n);
ans.x=ans.y=inf;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++) scanf("%d",&a[i][j]);
for (int i=;i<=n;i++)
for (int j=;j<=n;j++) scanf("%d",&b[i][j]);
point minx,miny;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++) val[i][j]=-a[i][j];
minx=km();
for (int i=;i<=n;i++)
for (int j=;j<=n;j++) val[i][j]=-b[i][j];
miny=km();
solve(minx,miny);
printf("%d\n",ans.x*ans.y);
}
return ;
}

bzoj3571: [Hnoi2014]画框 最小乘积匹配+最小乘积XX总结,的更多相关文章

  1. BZOJ3571 [Hnoi2014]画框 【分治 + KM算法】

    题目链接 BZOJ3571 题解 如果知道最小乘积生成树,那么这种双权值乘积最小就是裸题了 将两权值和作为坐标,转化为二维坐标系下凸包上的点,然后不断划分分治就好了 这里求的是最小匹配值,每次找点套一 ...

  2. BZOJ3571 : [Hnoi2014]画框

    题目是要求最小乘积最小权匹配, 将一种方案看做一个二维点(x,y),x=a值的和,y=b值的和,所有方案中只有在下凸壳上的点才有可能成为最优解 首先要求出两端的方案l,r两个点 l就是a值的和最小的方 ...

  3. 【算法】最小乘积生成树 & 最小乘积匹配 (HNOI2014画框)

    今天考试的时候果然题目太难于是我就放弃了……转而学习了一下最小乘积生成树. 最小乘积生成树定义: (摘自网上一篇博文). 我们主要解决的问题就是当k = 2时,如何获得最小的权值乘积.我们注意到一张图 ...

  4. BZOJ 3571 [Hnoi2014]画框(最小乘积完美匹配)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3571 [题目大意] 给出一张二分图,每条边上有a,b两个值,求完美匹配, 使得suma ...

  5. bzoj3571————2016——3——12(最小乘积匹配)

    bzoj3571 传送门http://www.lydsy.com/JudgeOnline/problem.php?id=3571 题解: ——————来自伟大的thy大神  http://blog.c ...

  6. GCJ:2008 Round1AA-Minimum Scalar Product(有序数组倒序乘积和最小)

    题目链接:https://code.google.com/codejam/contest/32016/dashboard#s=p0 Minimum Scalar Product This contes ...

  7. BZOJ3571 & 洛谷3236:[HNOI2014]画框——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3571 https://www.luogu.org/problemnew/show/P3236 小T ...

  8. nyoj 237 游戏高手的烦恼 二分匹配--最小点覆盖

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=237 二分匹配--最小点覆盖模板题 Tips:用邻接矩阵超时,用数组模拟邻接表WA,暂时只 ...

  9. HDU(1853),最小权匹配,KM

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...

随机推荐

  1. Google Code Jam 第一题

    通过的第一题,留做纪念,呵呵,非常简单,Africa 2010, Qualification Round: Store Credit. #include <stdio.h> #includ ...

  2. (太强大了) - Linux 性能监控、测试、优化工具

    转: http://www.vpsee.com/2014/09/linux-performance-tools/ Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经 ...

  3. 教程-Delphi MSComm 实时串口通讯

    Delphi  MSComm 实时串口通讯 MSComm控件具有丰富的与串口通信密切相关的属性,提供了对串口进行的多种操作,进而使串行通信变得十分简便.MSComm的控件属性较多,常用的属性如下:1) ...

  4. mongodb集成spring

    1:首先需要下载mongodb的java驱动包 https://github.com/mongodb/mongo-java-driver/downloads 2:需要下载spring集成mongodb ...

  5. [二]JFreeChart实践一

    生成一张简单的图片 java代码: package com.lxl.chart; import javax.servlet.http.HttpSession; import org.jfree.cha ...

  6. css3划过图片闪光

    css代码 01 .img { display:block; position: relative; width:800px; height:450px; margin:0 auto;} 02 .im ...

  7. 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...

  8. codis集群和redis cluster的优劣对比

    1.codis架构如下: (1)Codis是一整套缓存解决方案,包含高可用.数据分片.监控.动态扩态 etc..走的是 Apps->代理->redis cluster,一定规模后基本都采用 ...

  9. SimpleDateFormat 转化毫秒到日期时,指定特定的时区

    http://blog.csdn.net/wangpeng047/article/details/8560690 影响TimeZone的因素: 1. 操作系统的时区设置. 2. 数据传输时时区设置. ...

  10. "判断this指针是不是null有什么意义呢"

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:"判断this指针是不是null有什么意义呢".