洛谷 P3381 【模板】最小费用最大流

任重而道远

题目描述

如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

输入输出格式

输入格式:

第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。

输出格式:

一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。

AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int M = 5e4 + 10;
const int N = 5e3 + 10;
const int INF = 1e9 + 7;
struct edge {
    int tov, nxt, flw, val;
}e[M << 2];
int num = 1, src, sink, n ,m, maxflow = 0, mincost = 0;
int head[M << 1], dis[N], pree[N], prev[N];
bool vis[N];

void add_edge ( int u, int v, int w, int f ) {
    num++;
    e[num].tov = v;
    e[num].nxt = head[u];
    e[num].flw = f;
    e[num].val = w;
    head[u] = num;
    num++;
    e[num].tov = u;
    e[num].nxt = head[v];
    e[num].flw = 0;
    e[num].val = -w;
    head[v] = num;
}

bool spfa () {
    memset (dis, 0x7f, sizeof (dis));
    memset (vis, false, sizeof (vis));
    queue <int> q;
    q.push (src);
    dis[src] = 0;
    vis[src] = true;
    while (!q.empty ()) {
        int u = q.front ();
        q.pop ();
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].tov;
            if (e[i].flw && dis[u] + e[i].val < dis[v]) {
                dis[v] = dis[u] + e[i].val;
                pree[v] = i;
                prev[v] = u;
                if (!vis[v]) {
                    q.push (v);
                    vis[v] = true;
                }
            }
        }
        vis[u] = false;
    }
    return dis[sink] < dis[0];
}

void augment () {
    int u = sink;
    int delta = INF;
    while (u != src) {
        if (e[pree[u]].flw < delta)
          delta = e[pree[u]].flw;
        u = prev[u];
    }
    u = sink;
    while (u != src) {
        e[pree[u]].flw -= delta;
        e[pree[u] ^ 1].flw += delta;
        u = prev[u];
    }
    maxflow += delta;
    mincost += delta * dis[sink];
}

int main () {
    scanf ("%d%d%d%d", &n, &m, &src, &sink);
    for (int i = 1; i <= m; i++) {
        int u, v, w, f;
        scanf ("%d%d%d%d", &u, &v, &w, &f);
        add_edge (u, v, f, w);
    }
    while (spfa ())
      augment ();
    printf ("%d %d", maxflow, mincost);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/INTEGRATOR_37/article/details/80139333
今日推荐