网络流

网络流

bfs:对整张网络图进行分层,dfs一次就要分一次层,因为在dfs后有些流量会变成0;

dfs:求从起点到终点的一条路径的最大流 

dinic:分层成功后,然后跑dfs,再累加最大流

#include<bits/stdc++.h>
using namespace std;
int tot=1;//2,3一组 
const int INF=0x7f7f7f;
const int N=1e4+5;
const int M=2e5+5;//两倍数组 双向边 
int nex[M],head[N],to[M],from[M],cost[M],lev[N],s,t,n,m;
queue<int >q;
void add(int a,int b,int ww)
{
    tot++; from[tot]=a; to[tot]=b; cost[tot]=ww; nex[tot]=head[a]; head[a]=tot;
}
bool bfs()
{
    memset(lev,-1,sizeof(lev));
    lev[s]=0; q.push(s);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=head[u];i!=-1;i=nex[i])
        {
            int v=to[i];
            if(cost[i]!=0&&lev[v]==-1)
            lev[v]=lev[u]+1,q.push(v);
        }
    }
    if(lev[t]!=-1) return true;
    return false; 
}
int dfs(int u,int flow)
{
    if(u==t) return flow;
    int ret=flow;
    for(int i=head[u];i!=-1;i=nex[i])
    {
        if(ret<=0) break;
        int v=to[i];
        if(cost[i]&&lev[u]+1==lev[v])
        {
            int k=dfs(v,min(cost[i],ret));
            ret-=k; cost[i]-=k; cost[i^1]+=k; 
            //异或运算:2k^1=(2k+1) (2k+1)^1=2k;
        }
    }
    return flow-ret;//最大限制 - 还剩的多少没流 
}
void dinic()
{
    int ans=0;
    while(bfs())
    {
        ans+=(dfs(s,INF));
    }
    printf("%d
",ans);
}
int main()
{
    int x,y,z;
    memset(head,-1,sizeof(head));//head赋值成-1是为了当前弧优化 
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,0);//建反向边 为0 
    dinic();
}
原文地址:https://www.cnblogs.com/mowanying/p/10737425.html