完备匹配下的最大权匹配-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;}

原创粉丝点击