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神牛博客,并有所省略. [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和 ...
随机推荐
- 26、Python的可变类型和不可变类型?
Python的每个对象都分为可变和不可变 可变:列表.字典 不可变:数字.字符串.元祖 对不可变类型的变量重新赋值,实际上是重新创建一个不可变类型的对象,并将原来的变量重新指向新创建的对象(如果没有其 ...
- 蓝色的PC端后台管理界面设计模板——后台
链接:http://pan.baidu.com/s/1o82hXX4 密码:x6le
- 蓝色的cms网站后台管理模板——后台
链接:http://pan.baidu.com/s/1c138cwC 密码:9vy9
- 无状态Http
无状态的根本原因 浏览器和服务器使用socket通信,服务器将请求结果返回给浏览器后,会关闭当前socket连接.而且服务器会在处理页面完毕后销毁页面对象. 应用层面的原因 浏览器和服务器之间通信都遵 ...
- django 解决csrf跨域问题
1.中间件代码 [root@linux-node01 mysite]# tree middlewares middlewares ├── base.py ├── base.pyc ├── cors.p ...
- 非常粗糙的react网页ppt
import React, {Component} from 'react'; import './slide.css'; class Page extends Component { constru ...
- MVC公开课 – 1.基础 (2013-3-15广州传智MVC公开课)
1.MVC设计模式 Model 是指 要处理的业务代码和数据操作代码 View 视图 主要是指的 跟用户打交道 并能够展示数据 Controller 看成是 Model和View的桥梁 优点: 1.1 ...
- wordpress后台加载速度异常缓慢排查记录(原创)
原因在于在function.php函数中加入了下面的代码导致了缓慢: //停用版本更新通知remove_action('load-update-core.php', 'wp_update_themes ...
- Eolinker——前置用例返回的reponse值进行传递
如下补充均是Eolinker的文档中未说明的部分 示例:将login接口reponse中的mobile的值作为参数,传递给”重置密码”的请求体“code" 1.打开”前置用例“,先点击左上角 ...
- spring boot 扩展之AutoConfigurationImportListener
最近阅读spring boot源码时发现,发现当spring使用ConfigurationClassParser加载使用@Configuration注解类后,会使用AutoConfigurationI ...