KM算法模板

int maxData = 1000000000;    
int w[arraysize][arraysize];  //权值
int match[arraysize];         //保存匹配信息,其中i为Y中的顶点标号,match[i]为X中顶点标号
int lx[arraysize],ly[arraysize],slack[arraysize];  //lx[]为左顶点的顶标,ly[]为有顶点的顶标,slack[]记录右顶点的松弛量
bool finalx[arraysize],finaly[arraysize];     // 标记在一次DFS中,Xi与Yi是否在交错树上     
int ncount;
bool DFS(int p)
{
     int i,j,t;
     finalx[p] = true;      //将左顶点标记为真
     for(i=1;i<=ncount;++i)
     {
         if(finaly[i]) continue;
         int temp = lx[p]+ly[i]-w[p][i];
         if(temp==0)
         {
             finaly[i] = true;
             t = match[i];
             match[i] = p;
             if(t==0 || DFS(t))  return true;
             match[i] = t;
         }
         else if(slack[i]>temp)  //检查边(i,j)时,如果它不在相等子图中,则让slack[i]变成原值与A[p]+B[i]-w[p,i]的较小值
         {
             slack[i] = temp;
         }
     }
     return false;
}
int KM()
{
    int i,j;
    memset(ly,0,sizeof(ly));   //将右结点的可行顶标的值设置为0
    memset(match,0,sizeof(match));
    for(i=1;i<=ncount;++i)
    {
        lx[i]=-maxData;
        for(j=1;j<=ncount;++j)
        {
            if(lx[i]<w[i][j])     //将左顶点的可行顶标的值设置为所有与左顶点关联的边的最大权
                lx[i] = w[i][j];
        }
    }
    //从左顶点依次寻找增广路径
    for(i=1;i<=ncount;++i)
    {
        for(j=1;j<=ncount;++j) slack[j] = maxData;      //每次寻找增广路径将松弛量函数初始化无穷大
        while(1)
        {
            memset(finalx,0,sizeof(finalx));           
            memset(finaly,0,sizeof(finaly));
            if(DFS(i)) break;
            int d = maxData;
            for(j=1;j<=ncount;++j)          //d应该等于:Min{A[i]+B[j]-w[i,j] | Xi在交错树中,Yi不在交错树中}。
            {
                if(!finaly[j] && d>slack[j])
                   d = slack[j];
            }
            //若未找到完备匹配则修改可行顶标的值
            for(j=1;j<=ncount;++j)
            {
                if(finalx[j])  lx[j]-= d;
                if(finaly[j])  ly[j]+= d;
                else  slack[j] -= d;                  
            }
        }
    }
    int ans= 0;                //ans为权值和 
    for(i=1;i<=ncount;++i)
    {
        ans -=(lx[i]+ly[i]);
    }  
    return ans;
}

 

posted @ 2010-06-03 15:20  北海小龙  阅读(462)  评论(0编辑  收藏  举报