zoukankan      html  css  js  c++  java
  • 网络流求最大流算法

    一、网络流的定义:有向图G=(V,E)中,点集中有一源点S,一汇点T。且S入度为0,T出度为0。对于每条边edge,都有一权值函数c,表示其容量,一权值函数f,表示其实际流量。

    满足对于任意一条边都有f(edge)<=c(edge)。

    二、最大流的定义:在不违背网络流的定义下,S到T的最大流量。

    三、増广路的思想。

    我们先考虑一个网络流:红色数字表示实际流量,蓝色表示边的容量,黄色表示更优的流量。

    这个流从S到T的流量是5,但其显然不是最优的。

    这个流比上面那个优,而且事实上,这个流就是当前网络的最大流。

    我们将两个图比较,得出下图

    我们发现因为这条路径上的每条边流量都加了一。注意到其中有一条A到B的反向边,所以我们寻找这种路径时,应把原图中所有边的剩余流量和已经流量的反向边加进去(退流),当图中不存在这种路径时,此图已成最大流。(顺便提一下,这种路径叫増广路径)。

    四、求最大流的算法:

     FF:xyf大神说FF就是每次将源点的压力增加1,找一下増广路,慢点要死。于是直接上EK。

    EK:每次找一条増广路,将这条路径上所有的流量增加(不管正向反向,其实这里已经没有流量这个概念了)找到增广路径中最小的△。

    上代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    using namespace std;
    #define N 1100
    #define INF 0x3F3F3F3F
    struct note
    {
        int to,cap,rev;    
    };
    vector<note> path[N];
    bool used[N];
    int n,m;
    void make_way(int u,int v,int c)
    {
        path[u].push_back((note){v,c,path[v].size()});
        path[v].push_back((note){u,0,path[u].size()-1});
    }
    int dfs(int s,int t,int f)
    {
        if(s==t) return f;
        used[s]=1;
        for(int i=0;i<path[s].size();i++)
        {
            note &tmp=path[s][i];
            if(used[tmp.to]==false&&tmp.cap>0)
            {
                int d=dfs(tmp.to,t,min(f,tmp.cap));
                if(d>0)
                {
                    tmp.cap-=d;
                    path[tmp.to][tmp.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }
    int max_flow(int s,int t)
    {
        int flow=0;
        while(1)
        {
            memset(used,0,sizeof(used));
            int f=dfs(s,t,INF);
            if(f==0) return flow;
            flow+=f;
        }
    }
    int main()
    {
        scanf("%d %d",&m,&n);
        for(int i=1;i<=m;i++)
        {
            int u,v,c;
            scanf("%d %d %d",&u,&v,&c);
            make_way(u,v,c);
        }
        printf("%d
    ",max_flow(1,n));
    }

     dinic:就是先对图进行分层遍历,然后在分层图中进行dfs搜索,比EK快,10000的随即数据随便过。

  • 相关阅读:
    委托学习小记(1)
    C# 对XML的 创建、查询
    C#多线程学习(六) 互斥对象
    C#多线程学习(二) 如何操纵一个线程
    C#多线程学习(四) 多线程的自动管理(线程池)
    16/11/22_plsql
    写日志
    内存检测
    开源
    vs2005 远程调试。
  • 原文地址:https://www.cnblogs.com/dancer16/p/7225145.html
Copyright © 2011-2022 走看看