网络流基础

Posted vscoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流基础相关的知识,希望对你有一定的参考价值。

前言:

关于网络流,按董大佬的话,就是个板子,背下来就好了

正文:

最大流

最大流的基础求法就是増广路算法($EK$)

虽然它跑的慢,但也要会打,因为可以魔改求费用流

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>

using std::queue;
const int maxn=11111;
#define inf (0x3f3f3f3f)

class Max_Flow
{
    private:
        
        struct edge
        {
            int to,next,cap;
            edge(){}
            edge(int to,int next,int cap):to(to),next(next),cap(cap){}
        };
        
        edge e[maxn*20];
        int cnt,head[maxn];

        void add(int from,int to,int cap)
        {
            e[++cnt]=edge(to,head[from],cap);
            head[from]=cnt;
        }

        struct node
        {
            int pre,kth;
        };
        
        node p[maxn];
        bool vis[maxn];
    
        bool bfs(int s,int t)
        {
            memset(p,0,sizeof(p));
            memset(vis,0,sizeof(vis));
            queue<int>q;
            q.push(s);
            p[s].pre=s;
            vis[s]=1;
            while(!q.empty())
            {
                int u=q.front(); q.pop();
                for(int i=head[u];i!=-1;i=e[i].next)
                {
                    int v=e[i].to;
                    if(!vis[v]&&e[i].cap)
                    {
                        vis[v]=1;
                        p[v].pre=u;
                        p[v].kth=i;
                        if(v==t) return 1;
                        q.push(v);
                    }
                }
            } 
            return 0;
        }
        
    public:

        Max_Flow()
        {
            cnt=-1;
            memset(head,-1,sizeof(head));
        }
        
        void addedge(int u,int v,int w)
        {
            add(u,v,w);
            add(v,u,0);
        }
        
        int EK(int s,int t)
        {
            int maxflow=0;
            while(bfs(s,t))
            {
                int minn=inf;
                for(int i=t;i!=s;i=p[i].pre)
                    minn=std::min(minn,e[p[i].kth].cap);
                for(int i=t;i!=s;i=p[i].pre)
                {
                    e[p[i].kth].cap-=minn;
                    e[p[i].kth^1].cap+=minn;
                }
                maxflow+=minn;
            }
            return maxflow; 
        }
}flow;

int main()
{
    int n,m,s,t;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1,u,v,w;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        flow.addedge(u,v,w);
    }
    printf("%d
",flow.EK(s,t));
    return 0;
}

当然 $EK$ 的效率显然无法满足我们的要求

所以我们要进行优化,先将图进行分层,再去増广

于是我们有了 $Dinic$ 算法,还有基于它的各种鬼畜优化

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>

using std::queue;
const int maxn=11111;
#define inf (0x3f3f3f3f)

class Max_Flow
{

    private:

        struct edge
        {
            int to,next,cap;
            edge(){}
            edge(int to,int next,int cap):to(to),next(next),cap(cap){}
        };

        edge e[maxn*20];
        int cnt,head[maxn];

        void add(int from,int to,int cap)
        {
            e[++cnt]=edge(to,head[from],cap);
            head[from]=cnt;
        }

        int deep[maxn];

        bool bfs(int s,int t)
        {
            memset(deep,0,sizeof(deep));
            queue<int>q;
            q.push(s);
            deep[s]=1;
            while(!q.empty())
            {
                int u=q.front(); q.pop();
                for(int i=head[u];i!=-1;i=e[i].next)
                {
                    int v=e[i].to;
                    if(!deep[v]&&e[i].cap)
                    {
                        deep[v]=deep[u]+1;
                        if(v==t) return 1;
                        q.push(v);
                    }
                }
            }
            return 0;
        }

        int dfs(int u,int limit,int t)
        {
            if(u==t||!limit) return limit;
            int sum=0;
            for(int i=head[u];i!=-1;i=e[i].next)
            {
                int v=e[i].to;//关于当前弧优化,我并不会
                if(deep[v]==deep[u]+1&&e[i].cap)
                {
                    int flow=dfs(v,std::min(limit-sum,e[i].cap),t);
                    if(!flow) deep[v]=0;//据说叫炸点优化,感觉好霸气的样子
                    sum+=flow;
                    e[i].cap-=flow;
                    e[i^1].cap+=flow;
                    if(sum==limit) break;//这句剪枝一定要加上,否则真的不知道会差多少
                }
            }
            return sum;
        }

    public:

        Max_Flow()
        {
            cnt=-1;
            memset(head,-1,sizeof(head));
        }

        void addedge(int u,int v,int c)
        {
            add(u,v,c);
            add(v,u,0);
        }

        int Dinic(int s,int t)
        {
            int maxflow=0;
            while(bfs(s,t))
            {
                maxflow+=dfs(s,inf,t);
            }
            return maxflow;
        }

}flow;

int main()
{
    int n,m,s,t;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1,u,v,c;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&c);
        flow.addedge(u,v,c);
    }
    printf("%d
",flow.Dinic(s,t));
    return 0;
}

 还有一种 $ISAP$

以上是关于网络流基础的主要内容,如果未能解决你的问题,请参考以下文章

20155307刘浩《网络对抗》逆向及Bof基础

20155311高梓云《网络对抗》逆向及Bof基础

20145301赵嘉鑫《网络对抗》逆向及Bof基础

java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段

网络流总结费用流

java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段