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;
}
posted @ 2021-12-08 20:57  lahlah  阅读(68)  评论(0编辑  收藏  举报