Wannafly Camp 2020 Day 2I 堡堡的宝藏 - 费用流


感谢这道题告诉我KM求的是 完备 最大权匹配 :(

#include <bits/stdc++.h>
using namespace std;
#define reset(x) memset(x,0,sizeof x)
#define int long long
// Init: init() !!!!!
// Input: make(u,v,cap,cost)
// Solver: solve(s,t)
// Output: ans, cost
namespace flow {
const int N = 500005;
const int M = 1000005;
const int inf = 1e+14;
struct Edge {
    int p, c, w, nxt = -1;
} e[N];
int s, t, tans, ans, cost, ind, bus[N], qhead = 0, qtail = -1, qu[M],vis[N], dist[N];

void graph_link(int p, int q, int c, int w) {
    e[ind].p = q;
    e[ind].c = c;
    e[ind].w = w;
    e[ind].nxt = bus[p];
    bus[p] = ind;
    ++ind;
}
void make(int p, int q, int c, int w) {
    graph_link(p, q, c, w);
    graph_link(q, p, 0, -w);
}
int dinic_spfa() {
    qhead = 0;
    qtail = -1;
    memset(vis, 0x00, sizeof vis);
    memset(dist, 0x3f, sizeof dist);
    vis[s] = 1;
    dist[s] = 0;
    qu[++qtail] = s;
    while (qtail >= qhead) {
        int p = qu[qhead++];
        vis[p] = 0;
        for (int i = bus[p]; i != -1; i = e[i].nxt)
            if (dist[e[i].p] > dist[p] + e[i].w && e[i].c > 0) {
                dist[e[i].p] = dist[p] + e[i].w;
                if (vis[e[i].p] == 0)
                    vis[e[i].p] = 1, qu[++qtail] = e[i].p;
            }
    }
    return dist[t] < inf;
}
int dinic_dfs(int p, int lim) {
    if (p == t)
        return lim;
    vis[p] = 1;
    int ret = 0;
    for (int i = bus[p]; i != -1; i = e[i].nxt) {
        int q = e[i].p;
        if (e[i].c > 0 && dist[q] == dist[p] + e[i].w && vis[q] == 0) {
            int res = dinic_dfs(q, min(lim, e[i].c));
            cost += res * e[i].w;
            e[i].c -= res;
            e[i ^ 1].c += res;
            ret += res;
            lim -= res;
            if (lim == 0)
                break;
        }
    }
    return ret;
}
void solve(int _s,int _t) {
    s=_s; t=_t;
    while (dinic_spfa()) {
        memset(vis, 0x00, sizeof vis);
        ans += dinic_dfs(s, inf);
    }
}
void init() {
    memset(bus, 0xff, sizeof bus);
}
}
const int N = 2005;
int n,m,k;

int g[N][N];

void shmax(int &x,int y) {
    x=max(x,y);
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    flow::init();
    for(int i=1;i<=k;i++) {
        int x1,y1,x2,y2,w;
        cin>>x1>>y1>>x2>>y2>>w;
        int t1=x1*m-m+y1, t2=x2*m-m+y2;
        //cout<<t1<<" "<<t2<<endl;
        if((x1+y1)&1) flow::make(t1,t2,1,-w);
        else flow::make(t2,t1,1,-w);
    }
    for(int i=1;i<=n*m;i++) {
        int x1=(i-1)/m+1, y1=(i-1)%m+1;
        //cout<<i<<" "<<x1<<" "<<y1<<endl;
        if((x1+y1)%2==0) flow::make(i,n*m+2,1,0);
        flow::make(n*m+1,i,1,0);
    }
    flow::solve(n*m+1,n*m+2);
    cout<<-flow::cost;
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12333293.html