匈牙利算的是无权边二分图,而KM算法算的是有权边二分图
参考博客:https://blog.csdn.net/chenshibo17/article/details/79933191
模板代码:
#include<bits\stdc++.h> using namespace std; const int maxn=300+10; const int inf=1e9; int wx[maxn], wy[maxn]; //每个点的顶标值 int cx[maxn],cy[maxn]; //每个点所匹配的值 int visx[maxn],visy[maxn]; //每个点是否加入增广路 int cntx,cnty; int Map[maxn][maxn]; int minz; int n,k; bool dfs(int u) { visx[u]=1; for(int v=1;v<=cnty;v++) { if(!visy[v]&&Map[u][v]!=inf) { int t=wx[u]+wy[v]-Map[u][v]; if(t==0) { visy[v]=1; if(cy[v]==-1||dfs(cy[v])) { cx[u]=v; cy[v]=u; return 1; } } else if(t>0) { minz=min(minz,t); } } } return false; } int KM() { memset(cx,-1,sizeof(cx)); memset(cy,-1,sizeof(cy)); memset(wx,0,sizeof(wx)); memset(wy,0,sizeof(wy)); for(int i=1;i<=cntx;i++) { for(int j=1;j<=cnty;j++) { if(Map[i][j]==inf) continue; wx[i]=max(wx[i],Map[i][j]); } } for(int i=1;i<=cntx;i++) { while(1) { minz=inf; memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(dfs(i))break; for(int j=1;j<=cntx;j++) { if(visx[j]) { wx[j]-=minz; } } for(int j=1;j<=cnty;j++) { if(visy[i]) { wy[j]-=minz; } } } } int ans=0; for(int i=1;i<=cntx;i++) { if(cx[i]!=-1) { ans+=Map[i][cx[i]]; } } return ans; } int main() { while(~scanf("%d",&n)) { memset(Map,-1,sizeof(Map)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&Map[i][j]); } } cntx=cnty=n; printf("%d\n",KM()); } }