算法模板(8):网络流(3):费用流

算法模板(8):网络流(3):费用流

费用流之算法模板

费用流:所有最大可行流中,费用的最小值/最大值

注意费用指的是这条边的单位费用,即为 边的流量 乘 边的费用.

2174. 费用流 - AcWing题库

  • 题意:给定一个包含 n n n 个点 m m m 条边的有向图,并给定每条边的容量和费用,边的容量非负。图中可能存在重边和自环,保证费用不会存在负环。求从 S S S T T T 的最大流,以及在流量最大时的最小费用。
  • 每次沿着最短路增广,得到的费用是最小的。然后就是把 E K EK EK 算法中的 b f s bfs bfs 换成最短路即可,最短路中间加上对流量的更新即可。
#include
using namespace std;
const int N = 5010, M = 100010, INF = 1e8;
int h[N], e[M], ne[M], f[M], w[M], idx;

void add(int a, int b, int c, int d)
{
    e[idx] = b, ne[idx] = h[a], f[idx] = c, w[idx] = d, h[a] = idx++;
    e[idx] = a, ne[idx] = h[b], f[idx] = 0, w[idx] = -d, h[b] = idx++;
}
int n, m, S, T;
int incf[N], d[N], pre[N];
bool st[N];

bool spfa()
{
    memset(d, 0x3f, sizeof d);
    memset(incf, 0, sizeof incf);

    queue<int> que;
    d[S] = 0, incf[S] = INF;
    que.push(S);
    while(que.size())
    {
        int u = que.front(); que.pop();
        st[u] = false;
        for(int i = h[u]; i != -1; i = ne[i])
        {
            int v = e[i];
            if(f[i] && d[v] > d[u] + w[i])
            {
                d[v] = d[u] + w[i];
                pre[v] = i;
                incf[v] = min(f[i], incf[u]);
                if(!st[v])
                {
                    que.push(v);
                    st[v] = true;
                }
            }
        }
    }
    return incf[T] > 0;
}

void EK(int& flow, int& res)
{
    flow = 0, res = 0;
    while(spfa())
    {
        int t = incf[T];
        flow += t, res += t * d[T];
        for(int i = T; i != S; i = e[pre[i] ^ 1])
        {
            f[pre[i]] -= t, f[pre[i] ^ 1] += t;
        }
    }
}

int main()
{
    memset(h, -1, sizeof h);
    scanf("%d%d%d%d", &n, &m, &S, &T);
    for(int i = 1; i <= m; i++)
    {
        int a, b, c, d;
        scanf("%d%d%d%d", &a, &b, &c, &d);
        add(a, b, c, d);
    }
    int flow, res;
    EK(flow, res);
    printf("%d %d\n", flow, res);
    return 0;
}s

费用流之直接应用

费用流之二分图最优匹配

费用流之最大权不相交路径

费用流之网格图模型

费用流之拆点

费用流之上下界可行流

你可能感兴趣的:(算法模板,算法,图论,c++)