1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct Edge { int to, rev, cap, cost; };
struct MinCostMaxFlow {
int n; vector<vector<Edge>> g; vector<long long> pot, dist; vector<int> pv, pe;
MinCostMaxFlow(int n_) : n(n_), g(n_), pot(n_, 0), dist(n_), pv(n_), pe(n_) {}
void addEdge(int u, int v, int cap, int cost){
Edge a{v, (int)g[v].size(), cap, cost};
Edge b{u, (int)g[u].size(), 0, -cost};
g[u].push_back(a); g[v].push_back(b);
}
pair<int,long long> run(int s, int t){
const long long INF = (1LL<<60); int flow=0; long long cost=0;
while(true){
fill(dist.begin(), dist.end(), INF); fill(pv.begin(), pv.end(), -1); fill(pe.begin(), pe.end(), -1);
priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;
dist[s]=0; pq.push({0,s});
while(!pq.empty()){
auto [d,u]=pq.top(); pq.pop(); if(d!=dist[u]) continue;
for(int i=0;i<(int)g[u].size();++i){
const Edge &e=g[u][i]; if(e.cap<=0) continue;
long long nd=d+e.cost+pot[u]-pot[e.to];
if(nd<dist[e.to]){ dist[e.to]=nd; pv[e.to]=u; pe[e.to]=i; pq.push({nd,e.to}); }
}
}
if(dist[t]==INF) break;
for(int v=0; v<n; ++v) if(dist[v]<INF) pot[v]+=dist[v];
int add=INT_MAX; for(int v=t; v!=s; v=pv[v]) add=min(add, g[pv[v]][pe[v]].cap);
flow+=add; cost+=1LL*add*pot[t];
for(int v=t; v!=s; v=pv[v]){ Edge &e=g[pv[v]][pe[v]]; Edge &re=g[v][e.rev]; e.cap-=add; re.cap+=add; }
}
return {flow,cost};
}
};
int main(){
ios::sync_with_stdio(false); cin.tie(nullptr);
int N,M; if(!(cin>>N>>M)) return 0;
vector<int>A(N),B(M); for(int i=0;i<N;++i) cin>>A[i]; for(int i=0;i<M;++i) cin>>B[i];
vector<vector<int>> C(M, vector<int>(N)), D(M, vector<int>(N));
for(int i=0;i<M;++i) for(int j=0;j<N;++j) cin>>C[i][j];
for(int i=0;i<M;++i) for(int j=0;j<N;++j) cin>>D[i][j];
int S=0, store=1, person=store+M, T=person+N; MinCostMaxFlow mcmf(T+1);
for(int i=0;i<M;++i) if(B[i]>0) mcmf.addEdge(S, store+i, B[i], 0);
for(int i=0;i<M;++i) for(int j=0;j<N;++j) if(C[i][j]>0) mcmf.addEdge(store+i, person+j, C[i][j], D[i][j]);
for(int j=0;j<N;++j) if(A[j]>0) mcmf.addEdge(person+j, T, A[j], 0);
auto [flow, cost]=mcmf.run(S,T); cout<<flow<<"\n"<<cost<<"\n"; return 0;
}
|