BZOJ 3571 画框 KM算法 最小乘积最大权匹配
题意
有n个画框和n幅画。若第i幅画和第j个画框配对,则有平凡度Aij和违和度Bij,一种配对方案的总体不和谐度为∑Aij*∑Bij。求通过搭配能得到的最小不和谐度是多少。 n <= 70.
分析
这题是最小乘积最大权匹配裸题,其做法类似最小乘积生成树。
每个方案可以表示为二维平面上的点,答案必然在下凸壳上。
具体要怎么找呢?其实是有一个这样的方法:找出横坐标或纵坐标最小的点a和b,找点的方法可以用KM。
找到这两个点就可以分治下去做了,找到离直线ab距离最大的点(当然要在直线ab下方)。
列出点线距离公式,由于要找的点是在直线ab的下方,那么绝对值就可以去掉,整理为Ax+By的最值,然后就化成了一维,继续用KM来找,如此递归下去做。
当然,最小乘积XXX的东西似乎都可以用上面的方法做,拓展到多维方法也是类似的。
程序
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream> using namespace std; const int maxn = ;
const int INF = 0x3fffffff;
bool visx[maxn], visy[maxn];
int linker[maxn], slack[maxn], lx[maxn], ly[maxn], w[maxn][maxn];
int n, a[maxn][maxn], b[maxn][maxn];
struct Point
{
int x, y;
Point (int x = , int y = ):
x(x), y(y) {}
bool operator == (const Point &AI) const
{
return AI.x == x && AI.y == y;
}
}; bool dfs(int x)
{
int y, temp;
visx[x] = true;
for (y = ; y <= n; ++y)
{
if (visy[y]) continue ;
temp = lx[x]+ly[y]-w[x][y];
if (temp == )
{
visy[y] = true;
if (linker[y] == - || dfs(linker[y]))
{
linker[y] = x;
return true;
}
}
else if (temp < slack[y]) slack[y] = temp;
}
return false;
} Point KM()
{
int i, j, x, y, d;
memset(ly, , sizeof(ly));
memset(linker, -, sizeof(linker));
for (i = ; i <= n; ++i)
{
lx[i] = -INF;
for (j = ; j <= n; ++j) lx[i] = max(lx[i], w[i][j]);
}
for (x = ; x <= n; ++x)
{
for (y = ; y <= n; ++y) slack[y] = INF;
while ()
{
memset(visx, , sizeof(visx));
memset(visy, , sizeof(visy));
if (dfs(x)) break ;
d = INF;
for (y = ; y <= n; ++y) if (!visy[y]) d = min(d, slack[y]);
for (i = ; i <= n; ++i) if (visx[i]) lx[i] -= d;
for (y = ; y <= n; ++y)
if (visy[y]) ly[y] += d;
else slack[y] -=d;
}
}
Point temp(, );
for (i = ; i <= n; ++i)
temp.x += a[linker[i]][i], temp.y += b[linker[i]][i];
return temp;
} int solve(Point p1, Point p2)
{
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
w[i][j] = (p2.y-p1.y)*a[i][j]+(p1.x-p2.x)*b[i][j];
Point t = KM();
if (t == p1 || t == p2) return min(p1.x*p1.y, p2.x*p2.y);
return min(solve(p1, t), solve(t, p2));
} int main()
{
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
int T;
scanf("%d", &T);
while (T --)
{
scanf("%d", &n);
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 p1, p2;
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
w[i][j] = -a[i][j];
p1 = KM();
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
w[i][j] = -b[i][j];
p2 = KM();
printf("%d\n", solve(p1, p2));
}
return ;
}
BZOJ 3571 画框 KM算法 最小乘积最大权匹配的更多相关文章
- [BZOJ 3571] 画框
Link: BZOJ 3571 传送门 Solution: 和 BZOJ2395 的建模完全相同,(BZOJ2395 题解传送门) 仅仅是将其中的基础问题由最小生成树改成了二分图最大完美匹配 只要将原 ...
- hdu 3395(KM算法||最小费用最大流(第二种超级巧妙))
Special Fish Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- hdu 3488(KM算法||最小费用最大流)
Tour Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- 运动员最佳匹配问题 KM算法:带权二分图匹配
题面: 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势. ...
- hdu 4862 KM算法 最小K路径覆盖的模型
http://acm.hdu.edu.cn/showproblem.php?pid=4862 选t<=k次,t条路要经过全部的点一次而且只一次. 建图是问题: 我自己最初就把n*m 个点分别放入 ...
- bzoj 2395 [Balkan 2011]Timeismoney——最小乘积生成树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2395 如果把 \( \sum t \) 作为 x 坐标,\( \sum c \) 作为 y ...
- BZOJ.1497.[NOI2006]最大获利(最小割 最大权闭合子图Dinic)
题目链接 //裸最大权闭合子图... #include<cstdio> #include<cctype> #include<algorithm> #define g ...
- km板子(二分图最大权匹配)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack- ...
- 二分图带权匹配、最佳匹配与KM算法
---------------------以上转自ByVoid神牛博客,并有所省略. [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和 ...
随机推荐
- 深入理解Spring系列之一:开篇
转载 https://mp.weixin.qq.com/s?__biz=MzI0NjUxNTY5Nw==&mid=2247483810&idx=1&sn=a2df14fdb63 ...
- weblogic 包里面有中文文件名 会报错
目前:没有解决,只要有中文启动就报错 http://bbs.csdn.net/topics/10055670 http://www.2cto.com/os/201406/311394.html
- PXC加入新节点避免SST时grastate.dat文件内容的修改问题
PXC加入新节点避免SST时grastate.dat文件内容的修改问题 在主从同步完成并关闭实例后,需要修改grastate.dat中的seqno:到底应该填已经执行过最后的XID号(Executed ...
- python操作adb代码
adb命令的练习 #!/usr/bin/env python # encoding: utf-8 import os import re nameplt=re.compile("packag ...
- AssetBundle——外部加载资源Asset
几篇很不错的文章 AssetBundle创建到使用入门 全面理解Unity加载和内存管理 实用的创建AssetBundle的脚本 相关资源 相关的共享资源下载 本共享包括创建assetbund ...
- 对cgic的理解——name选项
#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cgic.h" ...
- CentOS6.9下安装MariaDB10.2.11
yum groupinstall -y "Development Tools" yum install -y cmake openssl-devel zlib-devel yum ...
- WordPress 用户管理插件 WP User Manager
WP User Manager 是一个较新的用户管理插件,可以在前端实现 用户注册.登录.找回密码.修改个人资料.修改密码等功能,如果你在找这方面的插件,WP User Manager 应该是一个不错 ...
- [你必须知道的.NET]第十九回:对象创建始末(下)
本文将介绍以下内容: 对象的创建过程 内存分配分析 内存布局研究 接上回[第十八回:对象创建始末(上)],继续对对象创建话题的讨论>>> 2.2 托管堆的内存分配机制 引用类型的实例 ...
- IE7、IE8下使用escape、encodeURI传递中文参数乱码的问题及解决方案
js跳转到指定页面,一旦escape()中文数据,浏览器就会终止和没有反应.上网搜了半天始终不得解.一种说法是,escape中文之后,url中出现了%u,IE7和IE8拒绝执行.目前看来差不多是这样的 ...