参考博文:
匈牙利算法
1.复杂度:O(n2)
2.适用范围:增广路径求最大匹配,无权图
3.思想: dfs进行匹配,如果匹配冲突,则检查能否改变冲突顶点的配对
4.代码实现:
- dfs代码模板:
int n,m;
int mp[maxn][maxn],match[maxn],used[maxn];
int dfs(int u)
{
for(int i = 1; i<=m; i++)
{
if(mp[u][i] && !used[i])
{
used[i] = 1;
if(match[i] == -1 || dfs(match[i]))
{
match[i] = u;
return 1;
}
}
}
return 0;
}
- 主函数
int res = 0; for(int i = 1; i<=n; i++) { memset(used, 0, sizeof(used)); if(dfs(i)) res++; }
KM算法
1.复杂度:O(n4),可以优化到O(n3)
2.适用范围:带权二分图的最佳匹配
3.思想:见https://www.cnblogs.com/logosG/p/logos.html
4.代码实现:
- dfs
int mp[maxn][maxn],expx[maxn],expy[maxn],visx[maxn],visy[maxn];
int match[maxn],slack[maxn];
int n,m;
int dfs(int u)
{
visx[u] = 1;
for(int i = 1; i<=n; i++)
{
if(visy[i] == 0)
{
int gap = expx[u] + expy[i] - mp[u][i];
if(gap == 0)
{
visy[i] = 1;
if(match[i] == -1 || dfs(match[i]))
{
match[i] = u;
return 1;
}
}
else slack[i] = min(slack[i],gap);
}
}
return 0;
}
- KM
int KM() { memset(match,-1,sizeof(match)); memset(expy,0,sizeof(expy)); for(int i = 1; i<=m; i++) { expx[i] = 0; for(int j = 1; j<=n; j++) expx[i] = max(expx[i],mp[i][j]); } for(int i = 1; i<=m; i++) { fill(slack+1,slack+1+n,INF); while(true) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(dfs(i))break; int d = INF; for(int j = 1; j<=n; j++) { if(visy[j] == 0) d = min(d,slack[j]); } for(int j = 1; j<=m; j++) if(visx[j]) expx[j] -=d; for(int j = 1; j<=n; j++) { if(visy[j]) expy[j] += d; else slack[j] -= d; } } } int res = 0; for(int i = 1; i<=n; i++) res += mp[match[i]][i]; return res; }