【模板】EK求最大流、dinic求最大流

ACM模板


概念

yxc老师的部分总结

1.1 流网络,不考虑反向边
1.2 可行流,不考虑反向边
1.2.1 两个条件:容量限制、流量守恒
1.2.2 可行流的流量指从源点流出的流量 - 流入源点的流量
1.2.3 最大流是指最大可行流
1.3 残留网络,考虑反向边,残留网络的可行流f’ + 原图的可行流f = 原题的另一个可行流
(1) |f’ + f| = |f’| + |f|
(2) |f’| 可能是负数
1.4 增广路径
1.5 割
1.5.1 割的定义
1.5.2 割的容量,不考虑反向边,“最小割”是指容量最小的割。
1.5.3 割的流量,考虑反向边,f(S, T) <= c(S, T)
1.5.4 对于任意可行流f,任意割[S, T],|f| = f(S, T)
1.5.5 对于任意可行流f,任意割[S, T],|f| <= c(S, T)
1.5.6 最大流最小割定理
(1) 可以流f是最大流
(2) 可行流f的残留网络中不存在增广路
(3) 存在某个割[S, T],|f| = c(S, T)

EK算法

链式前向星初始化-1版本 0正边 1反边
S源点 T汇点
d[]流量 pre[]前向边

存图存的是残留网络
时间复杂度: O ( n m 2 ) O(nm^2) O(nm2)

const int N=1010,M=20010;
int h[N],e[M],ne[M],f[M],idx;
int d[N],pre[N];
bool st[N];
int n,m,S,T;
void add(int a,int b,int c)
{
    
    
    e[idx]=b,ne[idx]=h[a],f[idx]=c;h[a]=idx++;
    e[idx]=a,ne[idx]=h[b],f[idx]=0,h[b]=idx++;
}
bool bfs()
{
    
    
    memset(st,0,sizeof st);
    queue<int> q;
    q.push(S);
    st[S]=1;
    d[S]=0x3f3f3f3f;
    while(q.size())
    {
    
    
        int t=q.front();q.pop();
        for(int i=h[t];i!=-1;i=ne[i])
        {
    
    
            int j=e[i];
            if(!st[j]&&f[i])
            {
    
    
                st[j]=1;
                d[j]=min(d[t],f[i]);
                pre[j]=i;  
                if(j==T) return 1;
                q.push(j);
            }
        }
    }
    return 0;
}
int EK()
{
    
    
    int r=0;
    while(bfs())
    {
    
    
        r+=d[T];
        for(int i=T;i!=S;i=e[pre[i]^1])
            f[pre[i]]-=d[T],f[pre[i]^1]+=d[T];
    }
    return r;
}

Dinic算法

模拟队列
时间复杂度: O ( n 2 m ) O(n^2m) O(n2m)

int h[N],e[M],ne[M],f[M],idx;
int S,T,d[N],q[N],cur[N];
void add(int a,int b,int c)
{
    
    
    e[idx]=b,ne[idx]=h[a],f[idx]=c,h[a]=idx++;
    e[idx]=a,ne[idx]=h[b],f[idx]=0,h[b]=idx++;
}
bool bfs()
{
    
    
    memset(d,-1,sizeof d);
    int tt=0,hh=0;
    q[S]=0,cur[S]=h[S],d[S]=0;
    while(hh<=tt)
    {
    
    
        int t=q[hh++];
        for(int i=h[t];i!=-1;i=ne[i])
        {
    
    
            int j=e[i];
            if(d[j]==-1&&f[i])
            {
    
    
                d[j]=d[t]+1;
                cur[j]=h[j];
                if(j==T) return 1;
                q[++tt]=j;
            }
        }
    }
    return 0;
}
int dfs(int u=S,int flow=0x3f3f3f3f)
{
    
    
    if(u==T) return flow;
    int rmn=flow;// 剩余流量
    for(int &i=cur[u];i!=-1&&rmn;i=ne[i])// 当前弧优化
    {
    
    
        int j=e[i];
        if(d[j]==d[u]+1&&f[i])
        {
    
    
            int t=dfs(j,min(f[i],rmn));
            if(!t) d[j]=-1;// 优化
            f[i]-=t,f[i^1]+=t,rmn-=t;
        }
    }
    return flow-rmn;
}
int dinic()
{
    
    
    int r=0;
    while(bfs()) r+=dfs();
    return r;
}

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/113007587
今日推荐