最小费用最大流

2024-08-15

采用Ford-Fulkerson方法和SPFA算法,求解最小费用最大流问题

#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
const int N = 1010;
int dis[N], pre[N], preve[N];
int n, m;
struct edge
{
    int to, cost, capacity, rev;
    edge(int to_, int cost_, int c, int rev_)
    {
        to = to_;
        cost = cost_;
        capacity = c;
        rev = rev_;
    }
};
vector<edge> e[N];
void addedge(int from, int to, int cost, int capacity)
{
    e[from].push_back(edge(to, cost, capacity, e[to].size()));
    e[to].push_back(edge(from, -cost, 0, e[from].size() - 1));
}
bool spfa(int s, int t, int cnt)
{
    bool inq[N];
    memset(pre, -1, sizeof(pre));
    for (int i = 1; i <= cnt; i++)
    {
        dis[i] = INF;
        inq[i] = false;
    }
    dis[s] = 0;
    queue<int> Q;
    Q.push(s);
    inq[s] = true;
    while (!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        inq[u] = false;
        for (int i = 0; i < e[u].size(); i++)
            if (e[u][i].capacity > 0)
            {
                int v = e[u][i].to, cost = e[u][i].cost;
                if (dis[u] + cost < dis[v])
                {
                    dis[v] = dis[u] + cost;
                    pre[v] = u;
                    preve[v] = i;
                    if (!inq[v])
                    {
                        inq[v] = true;
                        Q.push(v);
                    }
                }
            }
    }
    return dis[t] != INF;
}
int mincost(int s, int t, int cnt)
{
    int cost = 0;
    while (spfa(s, t, cnt))
    {
        int v = t, flow = INF;
        while (pre[v] != -1)
        {
            int u = pre[v], i = preve[v];
            flow = min(flow, e[u][i].capacity);
            v = u;
        }
        v = t;
        while (pre[v] != -1)
        {
            int u = pre[v], i = preve[v];
            e[u][i].capacity -= flow;
            e[v][e[u][i].rev].capacity += flow;
            v = u;
        }
        cost += dis[t] * flow;
    }
    return cost;
}
int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        for (int i = 0; i < N; i++)
            e[i].clear();
        for (int i = 1; i <= m; i++)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            addedge(u, v, w, 1);
            addedge(v, u, w, 1);
        }
        int s = n + 1, t = n + 2;
        addedge(s, 1, 0, 2);
        addedge(n, t, 0, 2);
        printf("%d\n", mincost(s, t, n + 2));
    }
    return 0;
}