完备匹配下的最大权匹配-KM算法的一般模板
来源:互联网 发布:斯拉夫人知乎 编辑:程序博客网 时间:2024/06/06 01:57
#include <iostream>#include<stdio.h>#include<cstring>#include<climits>#include<algorithm>using namespace std;const int maxn=305;int g[maxn][maxn],lx[maxn],ly[maxn];int match[maxn];bool visx[maxn],visy[maxn];int slack[maxn];int n;bool DFS(int cur)//匈牙利深度搜索算法{ visx[cur]=true; for(int y=1;y<=n;y++) { if(visy[y]) continue; int t=lx[cur]+ly[y]-g[cur][y]; if(t==0) { visy[y]=true; if(match[y]==-1||DFS(match[y])) { match[y]=cur; return true; } } else slack[y] = min(slack[y],t); //不在相等子图 }return false;}int KM_Maxmatch(){memset(match,-1,sizeof(match)); //初始化顶标memset(ly,0,sizeof(ly));//ly[i]为0for(int i=1;i<=n;i++){lx[i]=-INT_MAX;for(int j=1;j<=n;j++)//lx[i]为权值最大的边 { if(g[i][j]>lx[i]) lx[i]=g[i][j]; }}for(int k=1;k<=n;k++) //对n个点匹配{for(int m=1;m<=n;m++) slack[m]=INT_MAX; while(true) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(DFS(k)) break; //匹配成功 int d=INT_MAX;//匹配失败,找最小值 for(int i=1;i<=n;i++)//x在交错树中 { if(!visy[i]&&d>slack[i]) d=slack[i]; } for(int i=1;i<=n;i++)//y在交错树外 { if(visx[i]) lx[i]-=d; } for(int i=1;i<=n;i++)//更新顶标 { if(visy[i]) visy[i]+=d; else slack[i]-=d; } }}int result=0; //权值相加for(int i=1;i<=n;i++){ if(match[i]>-1) result+=g[match[i]][i];}return result;}int main(){ int i,j; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) for(j=1;j<=n;j++) scanf("%d",&g[i][j]); int ans=KM_Maxmatch(); printf("%d\n",ans); }return 0;}