【知识点】KM算法板子

求最大权值匹配

#include <bits/stdc++.h>
#define N 1500
#define inf 999999999
using namespace std;
int a[N],bs[N],nx=0,ny=0,k;
int linky[N],lx[N],ly[N],slack[N];
int visx[N],visy[N],w[N][N];
int min(int a,int b){return (a<b)?a:b;}
int find(int x){
    visx[x]=1;
    for(int y=1;y<=ny;y++){
        if(visy[y]) continue;
        int t=lx[x]+ly[y]-w[x][y];
        if(t==0){visy[y]=1;
            if(linky[y]==-1||find(linky[y])){
                linky[y]=x;return 1;
            }
        }
        else if(slack[y]>t) slack[y]=t;
    }
    return 0;
}
int km(){
    memset(linky,-1,sizeof(linky));
    memset(ly,0,sizeof(ly));
    for(int i=1;i<=nx;i++) lx[i]=-inf;
    for(int i=1;i<=nx;i++)for(int j=1;j<=ny;j++)if(w[i][j]>lx[i])lx[i]=w[i][j];
    for(int x=1;x<=nx;x++){
        for(int i=1;i<=ny;i++)
            slack[i]=inf;
        while(1){
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(find(x)) break;
            int d=inf;
            for(int i=1;i<=ny;i++) if(!visy[i]&&d>slack[i]) d=slack[i];
            for(int i=1;i<=nx;i++) if(visx[i]) lx[i]-=d;
            for(int i=1;i<=ny;i++) if(visy[i]) ly[i]+=d; else slack[i]-=d;
        }
    }
    int result=0;
    for(int i=1;i<=ny;i++)
    if(linky[i]>-1) result+=w[linky[i]][i];
    return result;
}
int main(){
    scanf("%d%d%d",&nx,&ny,&k);
    for(int i=1;i<=k;i++){
        int a,b,c;scanf("%d%d%d",&a,&b,&c);
        w[a][b]=c;
    }printf("%d\n",km());
    return 0;
}
posted @ 2020-01-11 09:17  carrotmvp  阅读(272)  评论(0编辑  收藏  举报