【知识点】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; }