做法见修车只是这题规模太大需要动态加边,就是每次增广完就加一层边,直到无法增广。
#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 2147483647
#define N 100005
#define M 3000005
using namespace std;
int n,m,tot,cnt=1,T,ans;
int t[45][105];
int c[45];
int dis[N],q[N],head[N],path[N];
int next[M],list[M],from[M],cost[M],flow[M];
bool vis[N];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void insert(int x,int y,int z,int w)
{
next[++cnt]=head[x];
head[x]=cnt;
from[cnt]=x;
list[cnt]=y;
flow[cnt]=z;
cost[cnt]=w;
}
inline bool spfa()
{
for (int i=0;i<=T;i++) dis[i]=inf;
int t=0,w=1,x;
q[1]=0; dis[0]=0; vis[0]=1;
while (t!=w)
{
t=(t+1)%N;
x=q[t];
for (int i=head[x];i;i=next[i])
if (flow[i]&&dis[list[i]]>dis[x]+cost[i])
{
dis[list[i]]=dis[x]+cost[i];
path[list[i]]=i;
if (!vis[list[i]])
{
vis[list[i]]=1;
w=(w+1)%N;
q[w]=list[i];
}
}
vis[x]=0;
}
return dis[T]!=inf;
}
inline void mcf()
{
int x=inf,a,b;
for (int i=path[T];i;i=path[from[i]])
{
x=min(x,flow[i]);
if (from[i]==0)
a=(list[i]-1)/tot+1,b=list[i]%tot+1;
}
for (int i=path[T];i;i=path[from[i]])
flow[i]-=x,flow[i^1]+=x,ans+=x*cost[i];
for (int i=1;i<=m;i++)
insert((a-1)*tot+b,n*tot+i,1,t[i][a]*b),insert(n*tot+i,(a-1)*tot+b,0,-t[i][a]*b);;
}
int main()
{
m=read(); n=read();
for (int i=1;i<=m;i++)
tot+=(c[i]=read());
for (int i=1;i<=m;i++)
for (int j=1;j<=n;j++)
t[i][j]=read();
T=n*tot+m+1;
for (int i=1;i<=n*tot;i++)
insert(0,i,1,0),insert(i,0,0,0);
for (int i=1;i<=m;i++)
insert(n*tot+i,T,c[i],0),insert(T,n*tot+i,0,0);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
insert((i-1)*tot+1,n*tot+j,1,t[j][i]),insert(n*tot+j,(i-1)*tot+1,0,-t[j][i]);
while (spfa()) mcf();
cout << ans << endl;
return 0;
}