var n,m,i,j:longint; ans:int64; sel,lx,ly,slack:array[1..100] of int64; a:array[1..100,1..100] of int64; visx,visy:array[1..100] of boolean; function dfs(po:longint):boolean; var i:longint; t:int64; begin visx[po]:=true; for i:=1 to m do if visy[i]=false then begin t:=lx[po]+ly[i]-a[po,i]; if t=0 then begin visy[i]:=true; if sel[i]=0 then begin sel[i]:=po; exit(true); end else if dfs(sel[i]) then begin sel[i]:=po; exit(true); end; end else if slack[i]>t then slack[i]:=t; end; exit(false); end; procedure km; var i,j:longint; d:int64; begin for i:=1 to n do lx[i]:=-100000*maxlongint; for i:=1 to n do for j:=1 to m do if a[i,j]>lx[i] then lx[i]:=a[i,j]; for i:=1 to n do begin while true do begin fillchar(visx,sizeof(visx),0); fillchar(visy,sizeof(visy),0); for j:=1 to m do slack[j]:=100000*maxlongint; if dfs(i) then break; d:=100*maxlongint; for j:=1 to m do if (visy[j]=false) and (slack[j]<d) then d:=slack[j]; for j:=1 to n do if visx[j] then dec(lx[j],d); for j:=1 to m do if visy[j] then inc(ly[j],d); end; end; end; begin read(n,m); for i:=1 to n do for j:=1 to m do begin read(a[i,j]); end; km; for i:=1 to n do ans:=ans+lx[i]; for i:=1 to m do ans:=ans+ly[i]; writeln(ans); end.
#include<cstdio> #include<iostream> #include<cmath> using namespace std; int m,n,k; int visx[1001],visy[1001],sel[1001]; long long lx[1001],ly[1001],a[1001][1001],slack[1001]; int dfs(int po){ visx[po]=1; for (int i=1;i<=m;i++) if (visy[i]==0){ long long t=lx[po]+ly[i]-a[po][i]; if (t==0){ visy[i]=1; if ((sel[i]==-1)||(dfs(sel[i]))){ sel[i]=po; return(1); } }else slack[i]=min(slack[i],t); } return(0); } void km(){ for (int i=1;i<=n;i++) lx[i]=-1e10; for (int i=1;i<=m;i++) ly[i]=0; for (int i=1;i<=m;i++) sel[i]=-1; for (int i=1;i<=n;i++) for(int j=1;j<=m;j++) lx[i]=max(lx[i],a[i][j]); for (int i=1;i<=n;i++) while (1){ for (int j=1;j<=n;j++) visx[j]=0; for (int j=1;j<=m;j++) visy[j]=0,slack[j]=1e10; if (dfs(i)) break; long long d=1e10; for (int j=1;j<=m;j++) if (visy[j]==0) d=min(d,slack[j]); for (int j=1;j<=n;j++) if (visx[j]) lx[j]-=d; for (int j=1;j<=m;j++) if (visy[j]) ly[j]+=d; } } int main(){ int T; scanf("%d",&T); while (T--){ scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[i][j]=0; for (int i=1;i<=k;i++){ int x,l,p,r; scanf("%d%d%d%d",&x,&l,&r,&p); for (int j=l;j<=r;j++) a[x][j]=p; } km(); long long ans1=0; for (int i=1;i<=n;i++) ans1+=lx[i]; for (int i=1;i<=m;i++) ans1+=ly[i]; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[i][j]*=-1; km(); long long ans2=0; for (int i=1;i<=n;i++) ans2-=lx[i]; for (int i=1;i<=m;i++) ans2-=ly[i]; if (ans1==ans2) printf("YES ");else printf("NO "); } }
求最小值所有边取相反数后KM,输出有答案的相反数
求最小乘积先求对数再KM