模板 KM算法

KM算法计算带权二分图最优匹配
时间复杂度\(O(n^3)\)
模板题:hdu2255 奔小康赚大钱

const int maxn=310;
const int inf=0x3f3f3f3f;

int n;
int g[maxn][maxn],ex1[maxn],ex2[maxn],match[maxn],slack[maxn];    
bool vis1[maxn],vis2[maxn];

bool dfs(int x){
    vis1[x]=true;
    for(int y=0;y<n;y++) {
        if(vis2[y]) continue; 
        int gap=ex1[x]+ex2[y]-g[x][y];
        if(gap==0){  
            vis2[y]=true;
            if(match[y]==-1 || dfs(match[y])){   
                match[y]=x;
                return true;
            }
        } 
        else{
            slack[y]=min(slack[y],gap);  
        }
    }
    return false;
}

int KM(){
    memset(match,-1,sizeof(match));    
    memset(ex2,0,sizeof(ex2));  
    for(int i=0;i<n;i++) {
        ex1[i]=g[i][0];
        for(int j=0;j<n;j++) {
            ex1[i]=max(ex1[i],g[i][j]);
        }
    }
    for (int i=0;i<n;i++) {
        memset(slack,0x3f,sizeof(slack));    
        while(1){
            memset(vis1,false,sizeof(vis1));
            memset(vis2,false,sizeof(vis2));
            if(dfs(i)) break;
            int d=inf;
            for (int j=0;j<n;j++)
                if(!vis2[j]) d=min(d,slack[j]);
            for (int j=0;j<n;j++){
                if(vis1[j]) ex1[j]-=d;
                if(vis2[j]) ex2[j]+=d;
                else slack[j]-=d;
            }
        }
    }
    int res=0;
    for(int i=0;i<n;i++)
        res+=g[match[i]][i];
    return res;
}
上一篇:kmeans算法


下一篇:训练指南 UVA - 11383(KM算法的应用 lx+ly >=w(x,y))