zoukankan      html  css  js  c++  java
  • 最大流最小割学习 基本知识 | 证明 | FF算法

    可行流 : 能流过去就行,不一定是最大流。

    最大流:能流到的最大流量。(可能不只一个)

    解决最大流:

      Ford-Fulkerson方法

     最小割:从图中去除一些边,使得源点S到汇点T不连通,去除的这些边权的权和最小,就是最小割

      PS!!!这个权和可以证明等于网络的最大流量!

     最大流等价于最小割!!!  求解最大流问题,也可以转化为最小割

    但是求最大流和求最小割集是两类不同的算法。求解最小割集普遍采用Stoer-Wagner算法

    1》》任意割大于等于任意流

      从源点到汇点必然经过割边(必然存在其中一条边是割边)那么令S - T的分支流分别为f1,f2,^...fn,f1 + f2 + …… fn = f

    (流——你可以少,但不能多,多过这条边的流限制就错了,所以,分割S,T集合后,流向T的必然会完全流入T,而割就是如何分割S,T

      所以f1<=c1,f2<= c2,f3 <= c3

      所以任意可行的割ci + cj + ck >= fi + fj + fk

    2》最大流 = 最小割

    (思考问题的时候要把每一条边分离出来看,对于合并的流也应该拆开)

      最大流是不能再流了,所以对于每一条分流中,必然存在一条边 i,使得fi == ci,对于这条边源头的流出目的是我要满足达到ci的流量即为最大流,且fi >= fk(k!=i),所以ci也是最小的容量

      所以对于每一个分流,我都会割取最小的容量边,而又因为是最大流,所以最小容量边必然满流,否则必然存在增广路径使的当前流变为最大流,所以最小割对应的容量即为最大流

    求解最大流算法:

      最简单的FF算法:

      当然因为简单易操作,所以时间复杂度较高,一般不会使用在ACM上,但一切都是以简单为基础的

      FF算法的思想:

        从s到t一直寻找可行最大流量,找到一个,最终的最大流加上它,然后就不找了,回溯,维护正向边和逆向边,然后回溯完了,进行适当的初始化后再重新找,直到找不到位置

      从我的描述方面就能看出,FF算法做了很多重复性的工作,一条边一条线可能被扫多次,但是没有标记这条边不可行,因为只有边可行才会维护删权

      接下来是代码

      

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define inf (1<<28)
    using namespace std;
    typedef long long ll;
    const int maxn = 1e4 + 1e2;
    const int maxm = 1e5 + 1e3;
    //n个点 m条边
    //从s - t求最大流
    int n,m,s,t;
    //链式前向星存储
    struct node
    {
        int to,cost,pre;
    }e[maxm<<1];
    int id[maxn],cnt;
    //最大流量ans
    ll ans;
    //dfs中
    bool vis[maxn],flag;
    void add(int from,int to,int cost)
    {
        e[cnt].to = to;
        e[cnt].cost = cost;
        e[cnt].pre = id[from];
        id[from] = cnt++;
    }
    int dfs(int now,int flow)
    {
        if(now == t)
        {
            flag = true;
            ans += flow;
            return flow;
        }
    
        vis[now] = 1;
    
        for(int i = id[now];~i;i = e[i].pre)
        {
            int to = e[i].to;
            int cost = e[i].cost;
    
            if(vis[to] || cost == 0)continue;
    
            int delta = dfs(to,min(flow,cost));
    
            if(flag)
            {
                e[i].cost -= delta;
                e[i^1].cost += delta;
                return delta;
            }
        }
        return 0;
    }
    void FF()
    {
        flag = false;
        memset(vis,0,sizeof(vis));
        dfs(s,inf);
        while(flag)
        {
            memset(vis,0,sizeof(vis));
            flag = false;
            dfs(s,inf);
        }
    }
    void init()
    {
        memset(id,-1,sizeof(id));
        cnt = 0;
        ans = 0;
    }
    int main()
    {
        while(~scanf("%d%d%d%d",&n,&m,&s,&t))
        {
            init();
            int from,to,cost;
            for(int i = 1;i <= m;++i)
            {
                scanf("%d%d%d",&from,&to,&cost);
                add(from,to,cost);
                add(to,from,0);
            }
            FF();
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Excel Sheet Column Number
    Compare Version Numbers
    Min Stack
    Excel Sheet Column Title
    Find Peak Element
    数据规范化
    Majority Element
    用户唯一登录
    面试总结——Java高级工程师(三)
    Spring AOP 实战运用
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9677740.html
Copyright © 2011-2022 走看看