同一条边可以经过多次,但仅有第一次经过时能够获得价值,可以建图:存在一条流量为 1 1 1 价值为 w w w 的边和一条流量为 i n f inf inf 价值为 0 0 0 的边。
建边方式比较变态,最后的 a a a 个出发点和 b b b 个终止点套用超级源点和超级汇点即可。
参考代码
#include <bits/stdc++.h>
#define itn int
#define int long long
#define endl "\n"
#define PII pair<int, int>
using namespace std;
const int N = 1e5 + 10;
const int M = 5e4 + 10;
const itn inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
//const int mod = 998244353;
template <int N>
struct MCMF {
struct E {
int to, cap, val, inv;
};
vector<E> g[N];
int dis[N], now[N], h[N], pre[N], preu[N];
void add(int u, int v, int f, int w) {
g[u].push_back({v, f, w, (int)g[v].size()});
g[v].push_back({u, 0, -w, (int)g[u].size() - 1});
}
void dijkstra(int st) {
priority_queue<pair<int, int>, vector<pair<int, int>>,
greater<pair<int, int>>>
q;
memset(dis, 0x3f, sizeof dis);
memset(pre, -1, sizeof pre);
memset(preu, -1, sizeof preu);
dis[st] = 0;
q.push({0, st});
while (q.size()) {
// auto [d, u] = q.top();
auto qnow = q.top();
int d = qnow.first, u = qnow.second;
q.pop();
if (dis[u] < d)
continue;
int x = 0;
for (auto gnow : g[u]) {
int v = gnow.to, f = gnow.cap, w = gnow.val, inv = gnow.inv;
if (f && dis[v] > dis[u] + w + h[u] - h[v]) {
dis[v] = dis[u] + h[u] - h[v] + w;
pre[v] = x;
preu[v] = u;
q.push({dis[v], v});
}
x++;
}
}
}
pair<int, int> min_cost_max_flow(int st, int ed) {
memset(h, 0, sizeof h);
for (int flow = 0, cost = 0, res = inf;; res = inf) {
dijkstra(st);
if (dis[ed] > inf)
return {flow, cost};
for (int i = 0; i < N; i++) {
h[i] += dis[i];
}
for (int i = ed; i != st; i = preu[i]) {
res = min(res, g[preu[i]][pre[i]].cap);
}
flow += res;
cost += res * h[ed];
for (int i = ed; i != st; i = preu[i]) {
g[i][g[preu[i]][pre[i]].inv].cap += res;
g[preu[i]][pre[i]].cap -= res;
}
}
}
};
MCMF<300> mcmf;
int id[20][20];
int n, k, s, t;
void solve() {
int a, b, p, q;
cin >> a >> b >> p >> q;
s = 0, t = 280;
int cnt = 0, x;
for (int i = 0; i <= p; i++) {
for (int j = 0; j <= q; j++) {
id[i][j] = ++cnt;
}
}
for (int i = 0; i <= p; i++) {
for (int j = 0; j < q; j++) {
cin >> x;
// cout << id[i][j] << " " << id[i][j+1] << endl;
mcmf.add(id[i][j], id[i][j + 1], 1, -x);
mcmf.add(id[i][j], id[i][j + 1], inf, 0);
}
}
for (int j = 0; j <= q; j++) {
for (int i = 0; i < p; i++) {
cin >> x;
// cout << id[i][j - 1] << " " << id[i][j] << endl;
mcmf.add(id[i][j], id[i + 1][j], 1, -x);
mcmf.add(id[i][j], id[i + 1][j], inf, 0);
}
}
for (int i = 1; i <= a; i++) {
int u, v;
cin >> x >> u >> v;
// cout << id[u][v] << endl;
mcmf.add(s, id[u][v], x, 0);
}
for (int i = 1; i <= b; i++) {
int u, v;
cin >> x >> u >> v;
// cout << id[u][v] << endl;
mcmf.add(id[u][v], t, x, 0);
}
cout << -mcmf.min_cost_max_flow(s, t).second << endl;
}
signed main() {
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cout << fixed << setprecision(12);
// init();
int T = 1;
// cin >> T;
while (T--) {
solve();
}
return 0;
}