1. 程式人生 > 實用技巧 >KM演算法(二分圖最大權匹配)

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; }