带权二分图——KM算法hdu2255 poj3565
进阶指南的板子好像有点问题。。交到hdu上会T
需要了解的一些概念:
交错树,顶标,修改量
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 99999999
#define maxn 305 int lx[maxn],ly[maxn];//顶标
int Match[maxn];//记录匹配值
int visx[maxn],visy[maxn];
int w[maxn][maxn];//权值
int slack[maxn];//slack为修改量
int ans,n; bool findPath(int x){
visx[x]=;
for(int y=; y<=n; y++){
if(visy[y])continue;
if(w[x][y]==lx[x]+ly[y]){//如果是相等子图则加入交错树中
visy[y]=;
if(!Match[y]||findPath(Match[y])){//增广后不用再考虑交错树
Match[y]=x;
return true;
}
}
else//不能加入交错树中的点,用来更新修改量
slack[y]=min(slack[y],lx[x]+ly[y]-w[x][y]);
}
return false;
}
void km(){
memset(Match,,sizeof(Match));
memset(lx,,sizeof(lx));
memset(ly,,sizeof(ly));
for(int i=; i<=n; i++)
for(int j=; j<=n; j++)
lx[i]=max(lx[i],w[i][j]); for(int x=; x<=n; x++){
for(int i=;i<=n;i++)slack[i]=INF;//初始化修改量
while(){
memset(visx,,sizeof(visx));
memset(visy,,sizeof(visy));
if(findPath(x))break;//直到x找到一个匹配点时退出循环
//如果没找到匹配点(增广失败),那么找最小修改量,
int tmp=INF;
for(int i=;i<=n;i++){
if(!visy[i]){
if(tmp>slack[i])
tmp=slack[i];
}
}
//更新交错树中的顶标
for(int i=; i<=n; i++){
if(visx[i]) lx[i]-=tmp;
if(visy[i]) ly[i]+=tmp;else slack[i]-=tmp;
}
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
ans=;
for(int i=; i<=n; i++)
for(int j=; j<=n; j++)
scanf("%d",&w[i][j]);
km();
for(int i=; i<=n; i++)
ans+=w[Match[i]][i];
printf("%d\n",ans);
}
return ;
}
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = ;
const double INF = 0xffffffffffff;
const double eps = 1e-; struct Node
{
double x,y;
}Dot1[MAXN],Dot2[MAXN]; double Dist(Node a,Node b)
{
return -sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
} int N,NX,NY;
double Map[MAXN][MAXN];
int link[MAXN];
double lx[MAXN],ly[MAXN],slack[MAXN];
int visx[MAXN],visy[MAXN]; int FindPath(int u)
{
visx[u] = ;
for(int i = ; i <= NY; ++i)
{
if(visy[i])
continue;
double temp = lx[u] + ly[i] - Map[u][i];
if(fabs(temp) <= eps)
{
visy[i] = ;
if(link[i] == - || FindPath(link[i]))
{
link[i] = u;
return ;
}
}
else
{
if(slack[i] > temp)
slack[i] = temp;
}
}
return ;
} void KM()
{
memset(lx,,sizeof(lx));
memset(ly,,sizeof(ly));
memset(link,-,sizeof(link));
for(int i = ; i <= NX; ++i)
{
lx[i] = -INF;
for(int j = ; j <= NY; ++j)
if(Map[i][j] > lx[i])
lx[i] = Map[i][j];
} for(int i = ; i <= NX; ++i)
{
for(int j = ; j <= NY; ++j)
slack[j] = INF;
while()
{
memset(visx,,sizeof(visx));
memset(visy,,sizeof(visy));
if(FindPath(i))
break;
double d = INF;
for(int j = ; j <= NY; ++j)
if(!visy[j] && d > slack[j])
d = slack[j];
for(int j = ; j <= NX; ++j)
if(visx[j])
lx[j] -= d;
for(int j = ; j <= NY; ++j)
{
if(visy[j])
ly[j] += d;
else
slack[j] -= d;
}
}
}
} int main()
{
int N;
while(~scanf("%d",&N))
{
memset(Map,,sizeof(Map));
for(int i = ; i <= N; ++i)
scanf("%lf%lf",&Dot1[i].x,&Dot1[i].y);
for(int i = ; i <= N; ++i)
scanf("%lf%lf",&Dot2[i].x,&Dot2[i].y); for(int i = ; i <= N; ++i)
for(int j = ; j <= N; ++j)
Map[i][j] = Dist(Dot1[i],Dot2[j]); NX = NY = N;
KM();
for(int i = ; i <= N; ++i)
{
for(int j = ; j <= N; ++j)
{
if(link[j] == i)
{
printf("%d\n",j);
break;
}
}
}
} return ;
}
带权二分图——KM算法hdu2255 poj3565的更多相关文章
- POJ3565带权匹配——km算法
题目:http://poj.org/problem?id=3565 神奇结论:当总边权最小时,任意两条边不相交! 转化为求二分图带权最小匹配. 可以用费用流做.但这里学一下km算法. https:// ...
- KM(Kuhn-Munkres)算法求带权二分图的最佳匹配
KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...
- 运动员最佳匹配问题 KM算法:带权二分图匹配
题面: 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势. ...
- HDU 2255 奔小康赚大钱(带权二分图最大匹配)
HDU 2255 奔小康赚大钱(带权二分图最大匹配) Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊 ...
- POJ 2195 Going Home (带权二分图匹配)
POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...
- Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配)
Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配) Description 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的 ...
- Glorious Brilliance (最短路 + 带权二分图匹配)
这是一道代码大题.一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!! 把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据01确定哪一些是需要更换状态的,然后建 ...
- [HAOI2008]移动玩具(状压&带权二分图)
题目描述 • 一个 4 × 4 的 0/1 矩阵 • 每次可以交换相邻两个元素 • 求从初始状态到目标状态的最小交换次数 输入格式 前四行,每行一个长为 4 的 0/1 字符串,描述初始状态. 后四行 ...
- POJ 2195 Going Home | 带权二分图匹配
给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...
随机推荐
- hexo next主题深度优化(二),懒加载。
文章目录 tip:没有耐心的可以直接看:正式在hexo next中加入懒加载(最下面) 废话 背景 懒加载简单介绍 引入js 重点!敲黑板了!!! 完善懒加载函数 懒加载函数可配置的参数 正式在hex ...
- 文本数据和mysql 里面的数据比较
实现读取TXT文件中的内容然后存到内存,然后将内存中的数据和mysql 数据库里面某张表数据的字段做一个比较,如果比较内存中的数据在mysql 里存在则不做处理,如果不存在则将该数据插入mysql数据 ...
- 本地 win7 与虚拟机Centos7 ping互通和Centos7 上网设置
VM 12 安装虚拟机我就不表示了 很简单网上找找 一 .虚拟机设置 1.修改使用了 VMWare 12 虚拟机,Oracle VM 用得有点晕 2.配置VM 的NET环境 3.在VMware虚拟机任 ...
- SQL Server实现跨库查询(跨库select insert)
方法一: select * from servername.dbo.tablename 方法二: select * from OPENDATASOURCE( 'SQLOLEDB', ...
- 事务和JDBC事务隔离级别
与事务相关的理论 mysql事物隔离级别:http://mj4d.iteye.com/blog/1744276 事务(Transaction): 是并发控制的单元,是用户定义的一个操作序列.这些操作要 ...
- linux命令输出到屏幕的同时保存到文件
有时候无法在一个屏幕中打印出所有显示内容 可以使用以下命令: ifconfig | tee ifconfig.log more ifconfig.log
- BCZM : 1.5
https://blog.csdn.net/zs634134578/article/details/18046317 有很多服务器存储数据,假设一个机器仅存储一个标号为ID的记录,假设机器总量在10亿 ...
- 93. 复原IP地址
题目描述: 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11.135&q ...
- P5390 [Cnoi2019]数学作业
P5390 [Cnoi2019]数学作业求子集异或和的和拆成2进制,假设有x个数这一位为1,剩下n-x个数对答案没有贡献,对于这一位而言,对答案的贡献就是,x个数选奇数个数的方案数*2^(n-x).由 ...
- leetcode-210-课程表②
题目描述: 第一次提交: class Solution: def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -& ...