二分图最佳匹配(kuhn munkras 算法 O(m*m*n))

本文详细介绍了Kuhn-Munkres算法用于求解二分图的最大匹配问题,包括邻接矩阵表示、时间复杂度分析以及算法的具体步骤。该算法确保找到一个最小权值的匹配,适用于m≤n的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分图最佳匹配( kuhn munkras 算法 O(m*m*n)
| 邻接距阵形式 , 复杂度 O(m*m*n) 返回最佳匹配值 , 传入二分图大小 m,n
| 邻接距阵 mat, 表示权 , match1,match2 返回一个最佳匹配 , 未匹配顶点
| match 值为 -1, 一定注意 m<=n, 否则循环无法终止 , 最小权匹配可将权值
| 取相反数
| 初始化: for( i=0 ; i < MAXN ; ++i )
for( j=0 ; j < MAXN ; ++j ) mat[i][j] = -inf;
| 对于存在的边: mat[i][j] = val ; // 注意,不能有负值
\*==================================================*/
#include <string.h>
#define MAXN 310
#define inf 1000000000
#define _clr(x) memset(x,-1,sizeof(int)*MAXN)
int kuhn_munkras(int m,int n,int mat[][MAXN],int*
match1,int* match2){
int
s[MAXN],t[MAXN],l1[MAXN],l2[MAXN],p,q,ret=0,i,j,k;
for (i=0;i<m;i++){
for (l1[i]=-inf,j=0;j<n;j++)
l1[i]=mat[i][j]>l1[i]?mat[i][j]:l1[i];
if( l1[i] == -inf ) return -1;// 无法匹配!
}
for (i=0;i<n;l2[i++]=0);
for (_clr(match1),_clr(match2),i=0;i<m;i++){
for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)
for (k=s[p],j=0;j<n&&match1[i]<0;j++)
if (l1[k]+l2[j]==mat[k][j]&&t[j]<0){
s[++q]=match2[j],t[j]=k;
if (s[q]<0)
for (p=j;p>=0;j=p)
match2[j]=k=t[j],p=match1[k],match1[k]=j;
}
if (match1[i]<0){
for (i--,p=inf,k=0;k<=q;k++)
for (j=0;j<n;j++)
if
(t[j]<0&&l1[s[k]]+l2[j]-mat[s[k]][j]<p)
p=l1[s[k]]+l2[j]-mat[s[k]][j];
for (j=0;j<n;l2[j]+=t[j]<0?0:p,j++);
for (k=0;k<=q;l1[s[k++]]-=p);
}
}
for (i=0;i<m;i++)
{// if 处理无匹配的情况!!
if( match[i] < 0 ) return -1;
if( mat[i][match[i]] <= -inf ) return -1;
ret+=mat[i][match1[i]];
}
return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千秋TʌT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值