最小费用流

题目描述

这是一道模板题。

给定 n 个点,m 条边,给定每条边的容量,求从点 s 到点 t 的最大流。

输入格式

第一行四个整数 n、m、s、t。
接下来的 m 行,每行三个整数 u 、v 、c,表示 u 到 v ,流量为 c 的一条边。

输出格式

输出点 s 到点 t 的最大流。

样例

样例输入
7 14 1 7
1 2 5
1 3 6
1 4 5
2 3 2
2 5 3
3 2 2
3 4 3
3 5 3
3 6 7
4 6 5
5 6 1
6 5 1
5 7 8
6 7 7
样例输出
14

数据范围与提示

1n106,1m4×106,0c2311

use Dijstra, O(fVlogE)

#include <stdio.h>
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <time.h>
//#include <unordered_map>
//#include <unordered_set>
#include <vector>
using namespace std;

#define mp make_pair
#define pb push_back
#define se second
#define fi first
#define rep(i, n) for(int i = 0; i < n; ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<int, int> pii;

const int MOD = (int)1e9 + 7;
const int INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const db PI = acos(-1.0);
const db EPS = 1e-10;

/*
const int MAXS = 64 * 1024 * 1024;
char buf[MAXS], *ch;
void read(int &x) {
    int t = 1;
    while(*ch <= 32) ++ch;
    //if(*ch == '-') ++ch, t = -1;
    for(x = 0; *ch >= '0'; ++ch) x = x * 10 + *ch - 48;
    //x = t * x;
}
void read_init() {
    fread(buf, sizeof(char), MAXS, stdin);
    ch = buf;
}
*/

const int MAXV = 405;
const int MAXE = 15005;

int V, E;

struct edge{
    int to, cap, cost, nxt;
    edge() {}
    edge(const int _to, const int _cap, const int _cost, const int _nxt) {
        to = _to;
        cap = _cap;
        cost = _cost;
        nxt = _nxt;
    }
}dat[MAXE<<1];

int head[MAXV], tail;

void add_edge(int from, int to, int cap, int cost) {
    dat[tail] = edge(to, cap, cost, head[from]);
    head[from] = tail++;
    dat[tail] = edge(from, 0, -cost, head[to]);
    head[to] = tail++;
}

int pre[MAXV], h[MAXV], dist[MAXV];

int min_cost_flow(int s, int t, int &f) {
    int res = 0;
    fill(h, h + V, 0);
    while(f > 0) {
        priority_queue<pii, vector<pii>, greater<pii> > que;
        fill(dist, dist + V, INF);
        dist[s] = 0;
        que.push(pii(0, s));
        while(!que.empty()) {
            pii p = que.top(); que.pop();
            int v = p.se;
            if(dist[v] < p.fi) continue;
            for(int i = head[v]; ~i; i = dat[i].nxt) {
                edge &e = dat[i];
                if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                    dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                    pre[e.to] = i;
                    que.push(pii(dist[e.to], e.to));
                }
            }
        }
        if(dist[t] == INF) return res; // return -1
        for(int v = 0; v < V; ++v) h[v] += dist[v];
        int d = f;
        for(int v = t; v != s; v = dat[pre[v]^1].to) {
            d = min(d, dat[pre[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for(int v = t; v != s; v = dat[pre[v]^1].to) {
            dat[pre[v]].cap -= d;
            dat[pre[v]^1].cap += d;
        }
    }
    return res;
}

int main()
{
    scanf("%d%d", &V, &E);
    int s = 0, t = V - 1;
    memset(head, 0xff, sizeof(head));
    tail = 0;
    int x, y, cap, cost;
    rep(i, E) {
        scanf("%d%d%d%d", &x, &y, &cap, &cost);
        add_edge(x - 1, y - 1, cap, cost);
    }
    int f = INF;
    int min_cost = min_cost_flow(s, t, f);
    printf("%d %d\n", INF - f, min_cost);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ctsas/article/details/79144806