网络流初步

网络流初步

贪心的说就是通过不停的搜s到t的路径,然后把所有的路径加起来。但这个贪心有点问题,自己本可以走另一条路,结果把别的路径的流量给抢了。所以增加了一个反向边的东西,有了这个东西,就给了路径反悔的机会。

Ford-Fulkerson算法

最朴素的算法(bushi),就是从s到t,一直dfs,满足条件增加流,否则退出。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
#define INF 0x7f7f7f7f
#define endl '
'
#define mem(a, b) memset(a, b, sizeof(a))
#define open freopen("ii.txt", "r", stdin)
#define close freopen("oo.txt", "w", stdout)
#define IO                       
    ios::sync_with_stdio(false); 
    cin.tie(0);                  
    cout.tie(0)
#define pb push_back
#define ll long long
using namespace std;
const int N = 210;
const double PI = 3.1415926535898;
///////

struct node
{
    ll to;
    ll cap;
    ll rev;
    node(ll a, ll b, ll c)
    {
        to = a;
        cap = b;
        rev = c;
    }
};
vector<node> e[N];//邻接表存图
int lev[N];//顶点到原点的距离标号
int iter[N];//当前弧,在此前面的都没用了。
//构建分层图
void bfs(int s)
{
    mem(lev, -1);
    queue<ll> q;
    lev[s]=0;
    q.push(s);
    while (!q.empty())
    {
        ll v = q.front();
        q.pop();
        for (int i = 0; i < e[v].size(); i++)
        {
            node &x = e[v][i];
            if (x.cap > 0 && lev[x.to] < 0)
            {
                lev[x.to] = lev[v] + 1;
                q.push(x.to);
            }
        }
    }
}
//找增广路
ll dfs(ll v, ll t, ll f)
{
    if (v == t)
        return f;
    for (int &i = iter[v]; i < e[v].size(); i++)
    {
        node &x = e[v][i];
        if (lev[v] < lev[x.to] && x.cap > 0)
        {
            ll d = dfs(x.to, t, min(f, x.cap));
            if (d > 0)
            {
                x.cap -= d;
                e[x.to][x.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}
//寻找最短路,先bfs构建分层图,然后dfs找增广路
ll max_flow(int s, int t)
{
    ll flow = 0;
    while (1)
    {
        bfs(s);
        if (lev[t] < 0)
            return flow;
        mem(iter, 0);
        ll f;
        while ((f = dfs(s, t, INF)) > 0)
        {
            flow += f;
        }
    }
}
int main()
{
    //open;
    ll n, m, s, t;
    scanf("%lld %lld %lld %lld", &n, &m, &s, &t);
    for (int i = 0; i < m; i++)
    {
        ll u, v, w;
        scanf("%lld%lld%lld", &u, &v, &w);
        e[u].pb(node(v, w, e[v].size()));//存入边,反向边要注意小细节。
        e[v].pb(node(u, 0, e[u].size() - 1));
    }
    ll ans = max_flow(s, t);
    printf("%lld
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Aracne/p/14773778.html