二分图最大匹配基础
这题是最大权二分图匹配模板
(小黄书上也是有的,讲解也很清晰)
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; int n,w[302][302],res,match[302],lx[302],ly[302],slack[302]; bool visx[302],visy[302]; inline void read(int &x){ char ch=getchar();x=0;int f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } inline bool dfs(int x){ visx[x]=true; for(int y=1;y<=n;y++){ if(visy[y])continue; int gap=lx[x]+ly[y]-w[x][y]; if(gap==0){ visy[y]=true; if(match[y]==-1 || dfs(match[y])){ match[y]=x;return true; } }else slack[y]=min(slack[y],gap); } return false; } inline void km(){ memset(match,-1,sizeof match); memset(ly,0,sizeof ly); for(int i=1;i<=n;i++){ lx[i]=w[i][1]; for(int j=2;j<=n;j++)lx[i]=max(lx[i],w[i][j]); } for(int i=1;i<=n;i++){ fill(slack,slack+n+1,0x3f3f3f3f); while(1){ memset(visx,false,sizeof visx);memset(visy,false,sizeof visy); if(dfs(i))break; int d=0x3f3f3f3f; for(int j=1;j<=n;j++)if(!visy[j])d=min(d,slack[j]); for(int j=1;j<=n;j++){ if(visx[j])lx[j]-=d; if(visy[j])ly[j]+=d; else slack[j]-=d; } } } } int main(){ while(~scanf("%d",&n)){ for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)read(w[i][j]); km(); res=0;for(int i=1;i<=n;i++)res+=w[match[i]][i]; printf("%d ",res); } return 0; }