AT4994 [AGC034D] Manhattan Max Matching
https://www.luogu.com.cn/problem/AT4994
考虑将曼哈顿距离的绝对值拆开,变成
又因为题目要求的也是最大价值和,所以可以叠加
直接用费用流即可
code:
#include<bits/stdc++.h>
#define N 200050
#define ll long long
using namespace std;
struct edge {
int v, nxt, c, w;
} e[N << 1];
int p[N], eid;
void init() {
memset(p, -1, sizeof p);
eid = 0;
}
void insert(int u, int v, int c, int w) {
e[eid].v = v;
e[eid].c = c;
e[eid].w = w;
e[eid].nxt = p[u];
p[u] = eid ++;
}
void add(int u, int v, int c, int w) {
insert(u, v, c, w), insert(v, u, 0, -w);
}
const int inf = 1e9;
int vis[N], pre[N], S, T;
ll dis[N];
queue<int> q;
int bfs() {
for(int i = 0; i <= T; i ++) vis[i] = 0, dis[i] = -1e18, pre[i] = -1;
dis[S] = 0; q.push(S);
while(q.size()) {
int u = q.front(); q.pop();
vis[u] = 0;
for(int i = p[u]; i + 1; i = e[i].nxt) {
int v = e[i].v, c = e[i].c, w = e[i].w;
if(dis[v] < dis[u] + w && c) {
dis[v] = dis[u] + w;
pre[v] = i;
if(!vis[v]) vis[v] = 1, q.push(v);
}
}
}
//for(int i = 1; i <= T; i ++) printf("%d ", pre[i]); printf("\n");
return pre[T] != -1;
}
ll mcmf() {
ll ret = 0, rett = 0;
for(; bfs() ; ) {
int flow = inf;
for(int u = T; u != S; u = e[pre[u] ^ 1].v)
flow = min(flow, e[pre[u]].c);
ret += flow;
for(int u = T; u != S; u = e[pre[u] ^ 1].v) {
e[pre[u]].c -= flow, e[pre[u] ^ 1].c += flow;
rett += 1ll * flow * e[pre[u]].w;
}
//break;
}
//printf(" %lld %lld\n", ret, rett);
return rett;
}
int n;
int main() {
init();
scanf("%d", &n);
int p1 = 2 * n + 1, p2 = p1 + 1, p3 = p2 + 1, p4 = p3 + 1;
S = p4 + 1, T = S + 1;
for(int i = 1; i <= n; i ++) {
int x, y, c;
scanf("%d%d%d", &x, &y, &c);
add(S, i, c, 0);
add(i, p1, inf, x + y);
add(i, p2, inf, x - y);
add(i, p3, inf, - x + y);
add(i, p4, inf, - x - y);
}
for(int i = n + 1; i <= 2 * n; i ++) {
int x, y, c;
scanf("%d%d%d", &x, &y, &c);
add(i, T, c, 0);
add(p1, i, inf, - x - y);
add(p2, i, inf, - x + y);
add(p3, i, inf, x - y);
add(p4, i, inf, x + y);
}
printf("%lld", mcmf());
return 0;
}