P3381 [模板] 最小费用最大流

EK  + dijkstra (2246ms) 开氧气(586ms)

dijkstra的势 可以处理负权 https://www.luogu.org/blog/28007/solution-p3381

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;

int n, m, s, t, cnt;

struct node {
    int to, nex, val, cost;
}E[100005];
int head[5005];

void addedge(int x, int y, int va, int cos) {
    E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos;
}

struct no1 {
    int to, edge;
}pre[5005];

struct no2 {
    int d, id;
    friend bool operator < (no2 A, no2 B) {
        return A.d > B.d;
    }
};

int dis[5005];
int h[5005];
bool dij() {

    for(int i = 1; i <= n; i++) dis[i] = INF;
    priority_queue<no2> que;

    dis[s] = 0;
    que.push((no2){0, s});

    while(!que.empty()) {
        no2 u = que.top();
        que.pop();
        if(dis[u.id] < u.d) continue;

        for(int i = head[u.id]; i; i = E[i].nex) {
            int v = E[i].to;
            if(E[i].val > 0 && dis[v] + h[v] > dis[u.id] + E[i].cost + h[u.id]) {
                dis[v] = dis[u.id] + E[i].cost + h[u.id] - h[v];
                pre[v].to = u.id;
                pre[v].edge = i;
                que.push((no2){dis[v], v});
            }
        }
    }
    if(dis[t] != INF) return true;
    else return false;
}

int ans, cos1;
void EK() {
    ans = cos1 = 0;

    while(dij()) {
        int mi = INF;
        for(int i = t; i != s; i = pre[i].to) {
            mi = min(mi, E[pre[i].edge].val);
        }
        for(int i = t; i != s; i = pre[i].to) {
            E[pre[i].edge].val -= mi;
            E[pre[i].edge ^ 1].val += mi;
        }
        for(int i = 1; i <= n; i++) h[i] += dis[i];
        ans += mi;
        cos1 += mi * h[t];
    }
}


int main() {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    cnt = 1;

    for(int i = 1; i <= m; i++) {
        int a, b, c, d;
        scanf("%d%d%d%d", &a, &b, &c, &d);
        addedge(a, b, c, d);
        addedge(b, a, 0, -d);
    }
    EK();
    printf("%d %d
", ans, cos1);
    return 0;
}
View Code

EK + spfa (1775ms) 开氧气(1398ms)

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;

int n, m, s, t, cnt;

struct node {
    int to, nex, val, cost;
}E[100005];
int head[5005];

void addedge(int x, int y, int va, int cos) {
    E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos;
}

struct no1 {
    int to, edge;
}pre[5005];

int dis[5005];
int vis[5005];

bool spfa() {
    memset(vis, 0, sizeof(vis));
    memset(dis, 0x3f, sizeof(dis));

    queue<int> que;
    que.push(s);
    vis[s] = 1;
    dis[s] = 0;
    while(!que.empty()) {
        int u = que.front();
        vis[u] = 0;
        que.pop();

        for(int i = head[u]; i; i = E[i].nex) {
            int v = E[i].to;
            if(E[i].val > 0 && dis[v] > dis[u] + E[i].cost) {
                dis[v] = dis[u] + E[i].cost;
                pre[v].to = u;
                pre[v].edge = i;
                if(!vis[v]) {
                    vis[v] = 1;
                    que.push(v);
                }
            }
        }
    }
    if(dis[t] != 0x3f3f3f3f) return true;
    else return false;
}

int ans, cos1;
void EK() {
    ans = cos1 = 0;

    while(spfa()) {
        int mi = INF;
        for(int i = t; i != s; i = pre[i].to) {
            mi = min(mi, E[pre[i].edge].val);
        }
        for(int i = t; i != s; i = pre[i].to) {
            E[pre[i].edge].val -= mi;
            E[pre[i].edge ^ 1].val += mi;
        }
        ans += mi;
        cos1 += mi * dis[t];
    }
}


int main() {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    cnt = 1;

    for(int i = 1; i <= m; i++) {
        int a, b, c, d;
        scanf("%d%d%d%d", &a, &b, &c, &d);
        addedge(a, b, c, d);
        addedge(b, a, 0, -d);
    }
    EK();
    printf("%d %d
", ans, cos1);
    return 0;
}
View Code

Dinic多路增广 + 弧优化 + spfa (1744ms) 

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;

int n, m, s, t, cnt;
int maxflow, mincost;

struct node {
    int to, nex, val, cost;
}E[100005];
int head[5005];
int cur[5005];

void addedge(int x, int y, int va, int cos) {
    E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos;
}

struct no1 {
    int to, edge;
}pre[5005];

int dis[5005];
int inque[5005];
int vis[5005];

bool spfa() {
    for(int i = 1; i <= n; i++) inque[i] = 0, dis[i] = 0x3f3f3f3f, cur[i] = head[i], vis[i] = 0;

    queue<int> que;
    que.push(s);
    inque[s] = 1;
    dis[s] = 0;
    while(!que.empty()) {
        int u = que.front();
        inque[u] = 0;
        que.pop();

        for(int i = head[u]; i; i = E[i].nex) {
            int v = E[i].to;
            if(E[i].val > 0 && dis[v] > dis[u] + E[i].cost) {
                dis[v] = dis[u] + E[i].cost;
                pre[v].to = u;
                pre[v].edge = i;
                if(!inque[v]) {
                    inque[v] = 1;
                    que.push(v);
                }
            }
        }
    }
    if(dis[t] != 0x3f3f3f3f) return true;
    else return false;
}

int dfs(int x, int flow) {
    if(x == t) {
        vis[x] = 1;
        maxflow += flow;
        return flow;
    }

    vis[x] = 1;
    int used = 0;
    int rflow = 0;
    for(int i = cur[x]; i; i = E[i].nex) {
        cur[x] = i;
        int v = E[i].to;
        if(E[i].val > 0 && dis[v] == dis[x] + E[i].cost && (!vis[v] || v == t)) {
            if(rflow = dfs(v, min(flow - used, E[i].val))) {
                used += rflow;
                E[i].val -= rflow;
                E[i ^ 1].val += rflow;
                mincost += E[i].cost * rflow;
                if(used == flow) break;
            }
        }
    }
    return used;
}

void dinic() {
    maxflow = mincost = 0;
    while(spfa()) {
        vis[t] = 1;
        while(vis[t]) {
            memset(vis, 0, sizeof(vis));
            dfs(s, INF);
        }
    }
}

int main() {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    cnt = 1;

    for(int i = 1; i <= m; i++) {
        int a, b, c, d;
        scanf("%d%d%d%d", &a, &b, &c, &d);
        addedge(a, b, c, d);
        addedge(b, a, 0, -d);
    }
    dinic();
    printf("%d %d
", maxflow, mincost);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/lwqq3/p/11143469.html