运动员最佳匹配问题 KM算法:带权二分图匹配
题面:
羽毛球队有男女运动员各n人。给定2 个n×n矩阵P和Q。P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势;Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势。由于技术配合和心理状态等各种因素影响,P[i][j]不一定等于Q[j][i]。男运动员i和女运动员j配对组成混合双打的男女双方竞赛优势为P[i][j]*Q[j][i]。设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。
题解:
看完题很容易发现这就是一个带权二分图匹配,
那么有两种选择:KM算法,费用流,
由于KM算法时间复杂度更优,这里选择KM算法,
以P[i][j]*Q[j][i]为边权直接匹配就好了
我是当KM算法模板做的,,,,
KM算法网上讲解也蛮多的,这里就不写了(其实是懒得画图)
这里运动员的数量很少,显然用邻接矩阵更合适,
匈牙利算法其实也可以看做是权值为1的带权二分图,
KM算法中也需要用到匈牙利,
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 24
int n,ans;
int tmp[AC][AC],s[AC][AC];
int vis[AC],z[AC];//vis = boy ,z = girl
int slack[AC];//对应的男生至少要降低多少权值
int link[AC],power_g[AC],power_b[AC];
/*km算法模板题*/ inline void upmax(int &a,int b)
{
if(b > a) a = b;
} inline void upmin(int &a,int b)
{
if(b < a) a = b;
} void pre()
{
scanf("%d",&n);
for(R i=;i<=n;i++)
for(R j=;j<=n;j++)
scanf("%d",&tmp[i][j]);
for(R i=;i<=n;i++)
for(R j=;j<=n;j++)
{
scanf("%d",&s[i][j]);
s[i][j] *= tmp[j][i];//求出每条边的权值
upmax(power_g[i],s[i][j]);//初始权值为所有权值里面最大的那个
}
} bool dfs(int x)
{
int now;
z[x]=true;
for(R i=;i<=n;i++)
{
if(vis[i]) continue;//每个男生只能访问一次
now=power_g[x] + power_b[i] - s[x][i];//获取权值和与边权之间的差距(一般会为正?)
if(!now)//如果刚好相等就连了
{
vis[i]=true;
if(!link[i] || dfs(link[i]))//如果对方还没有被匹配or之前那个人可以换走的话
{//因为要换走自己这边的人,所以是dfs(link[i])啊
link[i]=x;//就连上
return true;//其实这部分就是匈牙利
}
}
else upmin(slack[i],now);//不然就获取最小差距,以便调整权值时用
}
return false;//要是前面一直没有被匹配上
} void KM()
{
int x;
for(R i=;i<=n;i++)
{
memset(slack,,sizeof(slack));//因为要获取最小限度,所以初始化为极大值
while()//为什么一定要匹配满?貌似是题目要求,,,,
{
memset(vis,,sizeof(vis));
memset(z,,sizeof(z));
if(dfs(i)) break;//如果直接就配上了那就算了
x=INT_MAX;
for(R j=;j<=n;j++)
if(!vis[j]) upmin(x,slack[j]);//获取整张图的最小限度
for(R j=;j<=n;j++)
{//给涉及到的点修改权值
if(z[j]) power_g[j] -= x;//error!!!不要搞反了,是给女生降低,男生提高
if(vis[j]) power_b[j] += x;
else slack[j] -= x;//因为对面降低了,所以差距也小了
}
} }
for(R i=;i<=n;i++)
ans+=s[link[i]][i];//枚举男生,因为link[i]存的是男生对应的女生,所以只有男生才能获取到女生,反之不行
printf("%d\n",ans);
} int main()
{
// freopen("in.in","r",stdin);
pre();
KM();
// fclose(stdin);
return ;
}
运动员最佳匹配问题 KM算法:带权二分图匹配的更多相关文章
- KM算法 带权二分匹配 O(n^3)
#include<cstdio> #include<cstdlib> #include<cstring> #include<string> #inclu ...
- POJ 2195 Going Home (带权二分图匹配)
POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...
- 费用流模板(带权二分图匹配)——hdu1533
/* 带权二分图匹配 用费用流求,增加源点s 和 汇点t */ #include<bits/stdc++.h> using namespace std; #define maxn 1000 ...
- POJ 2195 Going Home | 带权二分图匹配
给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...
- hdu5045:带权二分图匹配
题目大意 : n个人 做m道题,其中 每连续的n道必须由不同的人做 已知第i人做出第j题的概率为pij,求最大期望 思路:考虑每连续的n道题 都要n个人来做,显然想到了带权的二分图匹配 然后就是套模板 ...
- Glorious Brilliance (最短路 + 带权二分图匹配)
这是一道代码大题.一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!! 把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据01确定哪一些是需要更换状态的,然后建 ...
- [NOI2012]美食节——费用流(带权二分图匹配)+动态加边
题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...
- [HAOI2008]移动玩具(状压&带权二分图)
题目描述 • 一个 4 × 4 的 0/1 矩阵 • 每次可以交换相邻两个元素 • 求从初始状态到目标状态的最小交换次数 输入格式 前四行,每行一个长为 4 的 0/1 字符串,描述初始状态. 后四行 ...
- KM(Kuhn-Munkres)算法求带权二分图的最佳匹配
KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...
随机推荐
- python3 小实践(一)——selenium获取的cookie传递
from selenium import webdriver from time import sleep import requests import pickle #获取登录后的cookies c ...
- Spring Cloud(五):Hystrix 监控面板【Finchley 版】
Spring Cloud(五):Hystrix 监控面板[Finchley 版] 发表于 2018-04-16 | 更新于 2018-05-10 | 在上一篇 Hystrix 的介绍中,我们提到 ...
- 【转】UTF8字符串转换为汉字 c#,转自游戏开发主席
using System; /// <summary> /// UTF8字符串转换为汉字用的类 /// 转换如"\\u8d35"之类的字符串为对应的汉字 /// < ...
- java扫描控制台输入
由于因最近练习算法的需要,加上API文档中翻译的太过模糊,做了一些小测试,算是武断的记下一些个人结论. Scanner cin = new Scanner(System.in); 对于cin.next ...
- [转载]CENTOS 6.0 iptables 开放端口80 3306 22端口
原文地址:6.0 iptables 开放端口80 3306 22端口">CENTOS 6.0 iptables 开放端口80 3306 22端口作者:云淡风轻 #/sbin/iptab ...
- 剑指offer-从上往下打印二叉树22
题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. class Solution: # 返回从上到下每个节点值列表,例:[1,2,3] def PrintFromTopToBottom( ...
- Django基本目录详解
1.app是自己建立的一个存放app的文件夹,因为项目大了之后会存在很多app(pycharm生成app方法 Tools-Run manage.py Task-输入startapp app名称) 2. ...
- linux 文件已经删除,但是空间没有释放的原因
监控系统报告一台服务器的空间满了,登陆后发现/tmp下有大量access_log文件,分析是Apache的日志文件很久没有清理了,确认并执行删除操作. 但是,问题来了,执行 rm /tmp/acces ...
- 左值&右值
一.引子 我们所谓的左值.右值,正确的说法应该是左值表达式.右值表达式. 因为C++的表达式不是左值就是右值. 在C中,左值指的是既能够出现在等号左边也能出现在等号右边的表达式,右值指的则是只能出现在 ...
- 路由器如何设置上网(TP-LINK)
最近宿舍公用的网络一直不太稳定,正赶上毕业季,本来就打算自己买一台自用的路由器,于是我从一个毕业的师姐手里15RMB收了一台路由器,师姐还给了我一根5m的网线和两根全新15m的,感觉光网线就赚翻了. ...