zoukankan      html  css  js  c++  java
  • P3376 【模板】网络最大流

    网络流

    一、概念


    网络流用于解决流量问题

    网络流:所有弧上流量的集合f={f(u,v)},称为该容量网络的一个网络流。

    1、定义:带权的有向图G=(V,E),满足以下条件,则称为网络流图(flow network):

    1. 仅有一个入度为0的顶点s,称s为源点。
    2. 仅有一个出度为0的顶点t,称t为汇点。
    3. 每条边的权值都为非负数,称为该边的容量,记作c(i,j)。

    2、弧的流量:通过容量网络G中每条弧< u,v>,上的实际流量(简称流量),记为f(u,v)。

    3、可行流:在容量网络G中满足以下条件的网络流f,称为可行流。

    a.弧流量限制条件:   0<=f(u,v)<=c(u,v);
    
    b:平衡条件:即流入一个点的流量要等于流出这个点的流量,(源点和汇点除外).

    4、零流 若网络流上每条弧上的流量都为0,则该网络流称为零流。 

    5、伪流:如果一个网络流只满足弧流量限制条件,不满足平衡条件,则这种网络流为伪流,或称为容量可行流.(预流推进算法有用)。

    6、对于网络流图G,流量最大的可行流f,称为最大流。

    7、弧的类型:

    1. a.饱和弧:即f(u,v)=c(u,v);
    2. b.非饱和弧:即f(u,v) < c(u,v);
    3. c.零流弧:即f(u,v)=0;
    4. d.非零流弧:即f(u,v)>0.

    8、链:

      在容量网络中,称顶点序列(u1,u2,u3,u4,..,un,v)为一条链要求相邻的两个顶点之间有一条弧.

      设P是G中一条从Vs到Vt的链,约定从Vs指向Vt的方向为正方向.在链中并不要求所有的弧的方向都与链的方向相同.

    性质

    1、对于任意一个时刻,设f(u,v)实际流量,则整个图G的流网络满足3个性质:

    1. 容量限制:对任意u,v∈V,f(u,v)≤c(u,v)。
    2. 反对称性:对任意u,v∈V,f(u,v) = -f(v,u)。从u到v的流量一定是从v到u的流量的相反值。
    3. 流守恒性:对任意u,若u不为S或T,一定有∑f(u,v)=0,(u,v)∈E。即u到相邻节点的流量之和为0,因为流入u的流量和u点流出的流量相等,u点本身不会"制造"和"消耗"流量。

    2、最大流最小割定理:一个图的最大流等于其最小割。(割掉每条可行流上的最小流量边)。

    Dinic算法:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<cstdlib>
    
    const int inf=0x7fffffff;
    
    using namespace std;
    
    int n,m,S,T;
    int a,b,c;
    int head[10008],vis[10008],dis[10008],num_edge=1;
    int deep[10008];
    
    struct Edge{
        int next,to,dis;
    }edge[100008<<1];
    
    queue <int> q;
    
    void addedge(int from,int to,int dis)
    {
        edge[++num_edge].next=head[from];
        edge[num_edge].to=to;
        edge[num_edge].dis=dis;
        head[from]=num_edge;
    }
    
    bool bfs()
    {
        memset(deep,0,sizeof(deep));
        while(!q.empty()) q.pop();
        deep[S]=1;
        q.push(S);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(deep[v]==0&&edge[i].dis)
                {
                    deep[v]=deep[u]+1;
                    q.push(v);
                }
            }
        }
        if(deep[T]==0) return 0;
        else return 1;
    }
    
    int dfs(int u,int dist)
    {
        if(u==T) return dist;
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(deep[v]==deep[u]+1&&edge[i].dis!=0)
            {
                int di=dfs(v,min(dist,edge[i].dis));
                if(di>0)
                {
                    edge[i].dis-=di;
                    edge[i^1].dis+=di;
                    return di;
                }
            }
        }
        return 0;
    }
    
    int Dinic()
    {
        int ans=0;
        while(bfs())
        {
            while(int di=dfs(S,inf))
            {
                ans+=di;
            }
        }
        return ans;
    }
    
    int main()
    {
        scanf("%d %d %d %d",&n,&m,&S,&T);
        for(int i=1;i<=m;++i)
        {
            scanf("%d %d %d",&a,&b,&c);
            addedge(a,b,c);
            addedge(b,a,c);
        }
        printf("%d",Dinic());
        return 0;
    }
  • 相关阅读:
    Oracle 游标
    对"com1"的访问被拒绝
    几种不伤身体的速效减肥秘方 生活至上,美容至尚!
    护肤必备,教你如何护理肌肤 生活至上,美容至尚!
    九种食物摆脱便秘烦恼 生活至上,美容至尚!
    1个多月就能看到效果的减肥大法 生活至上,美容至尚!
    防晒涂抹四大要领,让你远离日晒痛苦 生活至上,美容至尚!
    晚间保养四部曲 轻松护肤有妙招 生活至上,美容至尚!
    夏日驱蚊虫蟑螂的最好办法! 生活至上,美容至尚!
    睡前一分钟打造完美下半身 生活至上,美容至尚!
  • 原文地址:https://www.cnblogs.com/-hhs/p/10837568.html
Copyright © 2011-2022 走看看