• 网络流初步


    网络流初步

    贪心的说就是通过不停的搜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;
    }
    
  • 相关阅读:
    C++ 修改常量的值
    Android Studio 使用入门
    Ubuntu14.04下配置固定IP
    vi/vim 按键说明
    linux下文件夹的创建、复制、剪切、重命名、清空和删除命令
    linux中的find命令——查找文件名
    shell 脚本编写基础
    linux C程序中获取shell脚本输出(如获取system命令输出)
    vi 技巧
    理解Linux中的shutdown、poweroff、halt和reboot命令
  • 原文地址:https://www.cnblogs.com/Aracne/p/14773778.html
Copyright © 2020-2023  润新知