ISAP算法

2024-08-14

采用ISAP算法,求网络流的最大流

#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
using namespace std;
const LL INF = 1e9;
int n, m, s, t;
const int N = 250, M = 11000;
int cnt = 1, head[N];
struct
{
    int from, to, next, w;
} e[M];
void add(int u, int v, int w)
{
    cnt++;
    e[cnt].from = u;
    e[cnt].to = v;
    e[cnt].w = w;
    e[cnt].next = head[u];
    head[u] = cnt;
}
int now[M], pre[M];
int dep[M], gap[M];
void bfs()
{
    memset(gap, 0, sizeof(gap));
    memset(dep, 0, sizeof(dep));
    dep[t] = 1;
    queue<int> Q;
    Q.push(t);
    while (!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        gap[dep[u]]++;
        for (int i = head[u]; i > 0; i = e[i].next)
        {
            int v = e[i].to;
            if (e[i ^ 1].w && dep[v] == 0)
            {
                dep[v] = dep[u] + 1;
                Q.push(v);
            }
        }
    }
}
LL Augment()
{
    LL v = t, flow = INF;
    while (v != s)
    {
        int u = pre[v];
        if (e[u].w < flow)
            flow = e[u].w;
        v = e[u].from;
    }
    v = t;
    while (v != s)
    {
        int u = pre[v];
        e[u].w -= flow;
        e[u ^ 1].w += flow;
        v = e[u].from;
    }
    return flow;
}
void ISAP()
{
    bfs();
    LL flow = 0;
    int u = s;
    memcpy(now, head, sizeof(head));
    while (dep[s] <= n)
    {
        if (u == t)
        {
            flow += Augment();
            u = s;
        }
        bool ok = 0;
        for (int i = now[u]; i; i = e[i].next)
        {
            int v = e[i].to;
            if (e[i].w && dep[v] + 1 == dep[u])
            {
                ok = 1;
                pre[v] = i;
                now[u] = i;
                u = v;
                break;
            }
        }
        if (!ok)
        {
            if (!--gap[dep[u]])
                break;
            int mindep = n + 10;
            for (int i = head[u]; i; i = e[i].next)
            {
                int v = e[i].to;
                if (dep[v] < mindep && e[i].w)
                    mindep = dep[v];
            }
            dep[u] = mindep + 1;
            gap[dep[u]]++;
            now[u] = head[u];
            if (u != s)
                u = e[pre[u]].from;
        }
    }
    printf("%lld", flow);
}
int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for (int i = 1; i <= m; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w);
        add(v, u, 0);
    }
    ISAP();
    return 0;
}