//最大权匹配 bool sx[N],sy[N]; int nx,ny,g[N][N],lx[N],ly[N],cx[N],cy[N]; bool path(int u){//扩展二分图 判断是否存在由行元素u出发的可增广路径 int v; sx[u]=1; for(v=1;v<=ny;v++){ if(g[u][v]==lx[u]+ly[v]&&!sy[v]){ sy[v]=1; if(cy[v]==0||path(cy[v])){ cx[u]=v; cy[v]=u; return true; } } } return false; } int km(){ int i,j,u,min,ans=0; memset(ly,0,sizeof(ly)); memset(cx,0,sizeof(cx)); memset(cy,0,sizeof(cy)); for(i=1;i<=nx;i++){ lx[i]=-inf; for(j=1;j<=ny;j++) if(lx[i]<g[i][j]) lx[i]=g[i][j]; } for(u=1;u<=nx;u++){ memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); while(!path(u)){ min=inf; for(i=1;i<=nx;i++){ if(!sx[i]) continue; for(j=1;j<=ny;j++) if(!sy[j]&&lx[i]+ly[j]-g[i][j]<min) min=lx[i]+ly[j]-g[i][j]; } //调整顶标,二分图撤去该元素 for(i=1;i<=nx;i++) if(sx[i]){ lx[i]-=min; sx[i]=false; } for(i=1;i<=ny;i++) if(sy[i]){ ly[i]+=min; sy[i]=false; } } } for(i=1;i<=nx;i++) ans+=g[i][cx[i]]; return ans; }