带权二分图——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 ...
随机推荐
- jquery实现视频滚动
原理图 <!DOCTYPE html> <html lang="en"> <head> <script src="jquery. ...
- python学习6—数据类型之集合与字符串格式化
python学习6—数据类型之集合与字符串格式化 1. 使用id()可以查看一个变量的内存地址: name = 'alex' id(name) 2. 进制转换 十进制转换为二进制等: a = 10 # ...
- USACO2012 Broken necklace /// DP oj10103
题目大意: 项链最长的纯色连续段,“w”即white白色珠子,可任意涂为红或蓝,“r” “b”即红 蓝. Input Line 1: N, the number of beads Line 2: ...
- Spring MVC @RequestParam(5)
案例来说明 1 @RequestMapping("user/add") 2 public String add(@RequestParam("name") St ...
- spring @Transactional注解参数详解(13)
事物注解方式: @Transactional 当标于类前时, 标示类中所有方法都进行事物处理 , 例子: 1 @Transactional public class TestServiceBean i ...
- iOS音频开发系列-概述篇
概述 iOS中对于音频的处理,苹果提供了两个库. AVFoundation AudioToolbox 在iOS系统中apple对上述的流程进行了封装并提供了不同层次的接口
- jquery.js和jquery.min.js的区别和springboot整合echarts.min.js
1.区别:jquery官网提供2种jQuery的下载,一种是jquery.js另一种是jquery.min.js文件名不一定完全相同,但通常情况下:jquery.js是完整的未压缩的jQuery库,文 ...
- boost 条件变量
// boost 条件变量 // 做个简单的笔记 #include <boost/thread/mutex.hpp> #include <boost/thread/condition ...
- CSIC_716_20191126【面向对象编程--继承】
继承 什么是继承:继承是新建类的一种方式,通过此方式生成的类称为子类.或者 派生类,被继承的类称为父类.基类或超类.在python中,一个子类可以继承多个父类. 继承的作用:减少代码的冗余,提高开发效 ...
- promise 获取文件内容
文件结构图 { "next":"b.json", "msg":"this is a" } a.json { " ...