带权二分图——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 ...
随机推荐
- JVM内核-原理、诊断与优化学习笔记(九):锁
文章目录 线程安全 多线程网站统计访问人数 多线程访问ArrayList 对象头Mark Mark Word,对象头的标记,32位 描述对象的hash.锁信息,垃圾回收标记,年龄 偏向锁 轻量级锁 B ...
- ps-使用通道抠图为XX换背景
第一步先载入图片 点击通道,复制蓝色通道 然后点击新的蓝色通道,图像-调整-曲线-改变输入输出, 然后用历史画笔全部填黑. 然后载入选区,复制.在图层中新建蒙版 黏贴,反向(CTRL+I)就可以了. ...
- Linux ls 命令实现(简化版)
在学习linux系统编程的时候,实现了ls命令的简化版本号. 实现的功能例如以下: 1. 每种文件类型有自己的颜色 (- 普通文件, d 文件夹文件, l 链接文件. c 字符设备文件. b 快设备文 ...
- Spring MVC @CookieValue注解(5)
@CookieValue的作用 用来获取Cookie中的值 @CookieValue参数 1.value:参数名称 2.required:是否必须 3.defaultValue:默认值 @Cookie ...
- (二十三)Http请求的处理过程
- Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)
简单介绍一下,本框架的基本功能点: Spring:整个框架的主体部分,这个自不用说. SpringMVC:MVC部分我还是比较喜欢Spring的. MyBatis:选型的时候选择这个ORM主要也是考虑 ...
- java 与日期转换相关的方法(java.util.date类型和java.sql.date类型互相转换)、随机字符串生成方法、UUID生产随机字符串
package com.oop.util; import java.text.*; import java.util.UUID; import org.junit.Test; /* * 与日期相关的工 ...
- iOS开发系列-weak与unsafe_unretained修饰符
概述 在iOS内存管理中,为防止循环引用,定义类的内部对象属性使用weak.unsafe_unretained修饰符,不产生强引用. 开发中一般使用的weak修饰符,那么接下来说下weak跟unsaf ...
- RDD运行原理
- jpa 踩坑 SQLGrammarException
SQLGrammarException could not execute query cause by not found column id ,, id指的是,返回的结果没有Id 封装结果集出错 ...