题目链接:https://www.luogu.org/problem/P4015
最小/最大费用模板题
// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;
const int N = 300;
int n,m,S,T,tot;
int head[N];
struct node{
int v,cap,cost,nxt;
}edge[int(2e5+100)];
int dis[N],pre[N],last[N],flow[N],maxflow,mincost; //pre:前驱结点 last:每个点所连的前一条边 flow:源点到该点的流量
bool vis[N];
void ae(int u,int v,int cap,int cost){ //前向星加边
edge[++tot] = node{v,cap,cost,head[u]};
head[u] = tot;
}
bool spfa() {
memset(dis,0x7f,sizeof(dis));
memset(flow,0x7f,sizeof(flow)); //2e9
memset(vis,0,sizeof(vis));
deque<int> q;
q.push_back(S);
vis[S] = 1; dis[S] = 0; pre[T] = -1;
while(!q.empty()) {
int u = q.front();
q.pop_front();
vis[u] = 0;
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(edge[i].cap>0&&dis[v]>dis[u]+edge[i].cost) {
dis[v] = dis[u]+edge[i].cost;
pre[v] = u;
last[v] = i;
flow[v] = min(flow[u],edge[i].cap);
if(!vis[v]) {
vis[v] = 1;
if(dis[v]<=dis[u]) q.push_front(v);
else q.push_back(v);
}
}
}
}
return pre[T] != -1;
}
void dinic(){
while(spfa()){
int now = T;
maxflow += flow[T];
mincost += flow[T]*dis[T];
while(now!=S) {
edge[last[now]].cap -= flow[T];
edge[last[now]^1].cap += flow[T];
now = pre[now];
}
}
return ;
}
void init() {
mincost = 0;
maxflow = 0;
tot = -1;
memset(head,-1,sizeof(head));
}
int a[200],b[200],v[220][220];
int main() {
// freopen("a.txt","r",stdin);
// ios::sync_with_stdio(0);
cin>>n>>m;
S = 0;T = n+m+1;
init();
rep(i, 1, n) {
cin>>a[i];
ae(S,i,a[i],0);
ae(i,S,0,0);
}
rep(i, 1, m) {
cin>>b[i];
ae(n+i,T,b[i],0);
ae(T,n+i,0,0);
}
rep(i, 1, n)
rep(j, 1, m) {
cin>>v[i][j];
ae(i,n+j,1e9,v[i][j]);
ae(n+j,i,0,-v[i][j]);
}
dinic();
printf("%d\n",mincost);
init();
rep(i, 1, n) {
ae(S,i,a[i],0);
ae(i,S,0,0);
}
rep(i, 1, m) {
ae(n+i,T,b[i],0);
ae(T,n+i,0,0);
}
rep(i, 1, n)
rep(j, 1, m) {
v[i][j] = -v[i][j];
ae(i,n+j,1e9,v[i][j]);
ae(n+j,i,0,-v[i][j]);
}
dinic();
printf("%d\n",-mincost);
return 0;
}