题面:

羽毛球队有男女运动员各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算法:带权二分图匹配的更多相关文章

  1. KM算法 带权二分匹配 O(n^3)

    #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #inclu ...

  2. POJ 2195 Going Home (带权二分图匹配)

    POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...

  3. 费用流模板(带权二分图匹配)——hdu1533

    /* 带权二分图匹配 用费用流求,增加源点s 和 汇点t */ #include<bits/stdc++.h> using namespace std; #define maxn 1000 ...

  4. POJ 2195 Going Home | 带权二分图匹配

    给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...

  5. hdu5045:带权二分图匹配

    题目大意 : n个人 做m道题,其中 每连续的n道必须由不同的人做 已知第i人做出第j题的概率为pij,求最大期望 思路:考虑每连续的n道题 都要n个人来做,显然想到了带权的二分图匹配 然后就是套模板 ...

  6. Glorious Brilliance (最短路 + 带权二分图匹配)

    这是一道代码大题.一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!! 把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据01确定哪一些是需要更换状态的,然后建 ...

  7. [NOI2012]美食节——费用流(带权二分图匹配)+动态加边

    题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...

  8. [HAOI2008]移动玩具(状压&带权二分图)

    题目描述 • 一个 4 × 4 的 0/1 矩阵 • 每次可以交换相邻两个元素 • 求从初始状态到目标状态的最小交换次数 输入格式 前四行,每行一个长为 4 的 0/1 字符串,描述初始状态. 后四行 ...

  9. KM(Kuhn-Munkres)算法求带权二分图的最佳匹配

    KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...

随机推荐

  1. SpringBoot入门(五)——自定义配置

    本文来自网易云社区 大部分比萨店也提供某种形式的自动配置.你可以点荤比萨.素比萨.香辣意大利比萨,或者是自动配置比萨中的极品--至尊比萨.在下单时,你并没有指定具体的辅料,你所点的比萨种类决定了所用的 ...

  2. Java基础知识总结一

    1.何为编程? 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程. 为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路.方法.和手段通过计算机能够理解 ...

  3. 根据wsdl生成服务端代码

    场景描述 最近在和一家公司做业务接口对接,由他们那边回调我们这边,对方直接扔过来一个webservice的wsdl文件,让我们按照他们的规范来做webservice服务, 大多数的对接应该是我们创建完 ...

  4. WPF & EF & Prism useful links

    Prism Attributes for MEF https://msdn.microsoft.com/en-us/library/ee155691%28v=vs.110%29.aspx Generi ...

  5. Objective-C 点语法 成员变量的作用域 @property和@synthesize关键字 id类型

    点语法 1.利用点语法替换set方法和get方法 方法调用 Student *stu = [Student new]; [stu setAge : 18]; int age = [stu age]; ...

  6. ubuntu networking 与 network-manager

    刚遇到的坑,因为操作不当导致网络中断,于是手动配置了/etc/network/interfaces , 修复了系统之后发现ubuntu-desktop中的有线链接不见了,百度了一下说是networki ...

  7. anaconda安装scrapy报错解决办法

    今天在用anaconda安装scrapy的时候遇见个坑,现在将解决办法发出来,供大家参考使用: 问题描述: anaconda安装scrapy,使用 conda install scrapy 命令.安装 ...

  8. Linux下安装paramiko

    paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 由于使用的是python这样的能够跨平台运行的语言,所以所有python支持的平台, ...

  9. VBA基础之Excel 工作表(Sheet)的操作(二)

    二. Excel 工作表(Sheet)的操作1. Excel 添加工作表(Sheet) 方法名 参数 参数值 说明 Add Before 工作表名称 在指定的工作表前面插入新的工作表 After 工作 ...

  10. 每周psp-第五周

    PSP表格: 类别 任务 开始时间 结束时间 中断时间 delta时间 开会 scrum立会 10.13下午6:04 10.13下午6:34 0 30 开会 scrum立会 10.14下午6:02 1 ...