KM模板

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

原文地址:https://www.cnblogs.com/zhujiangning/p/5212818.html