图论——网络流——最大流(1.0版 强化)

https://www.cnblogs.com/LUO77/p/6115057.html
https://www.cnblogs.com/linzhengmin/p/9313216.html
https://blog.youkuaiyun.com/pi9nc/article/details/11860409

Dinic算法

1、矩阵版模板(适用于顶点少的情况)

#include<queue>
#include<cstdio>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
#define N 1001
using namespace std;
int E, V;//V个点E条边
int S,T;//源点、汇点
int level[N];//存储结点分层层数

struct Edge
{
    int cap;
    int flow;
} edge[N][N];

bool bfs() //构造层次网络
{
    memset(level,0,sizeof(level));/***初始化 为 层次0***/
    queue<int> Q;
    Q.push(S);
    level[S]=1;/**源点S 的 层次 为 1**/
    
    while(!Q.empty())
    {
        int x=Q.front();
        Q.pop();
        for(int y=1; y<=n; y++)
        {
            if(!level[y]&&edge[x][y].cap>edge[x][y].flow)/****y点还未在构次网络中**并且*如果剩余流量大于 0 , 就将其构造进层次网络****/
            {
                level[y]=level[x]+1;/***y 的层次 是他 x +1***/
                Q.push(y);
            }
        }
    }
    return level[T]!=0;/******T节点为 0  表示 没有 构造出 到 T(汇点)的 层次网络****/
}



/********************

在 层次网络上寻找增广路,计算可增加流量,↓↓

****************/
int dfs(int x,int cp)/******  cp 表示上一次的最小流量, 第一次cp 初始化为 INF ***/
{
    if(x==n)/********递归边界*****/
        return cp;

    int flow=cp;//记录从x到t的最小残量
    for(int y=1; y<=n; y++)
    {
        if(level[x]+1==level[y])/****寻找下一层*****/
        {
            if(edge[x][y].cap>edge[x][y].flow)
            {
                int minn=min(flow,edge[x][y].cap-edge[x][y].flow);/********增量 取决与该增广路最小的流量*********/
                int newFlow=dfs(y,minn);/*******************************/
                edge[x][y].flow+=newFlow;
                edge[y][x].flow-=newFlow;
                flow-=newFlow;
            }
        }
    }

    return cp-flow;/*****cp - flow 是增加量********/
}


int dinic()
{
    int flow=0;
    int tf=0;/***增量***/
    while(bfs())/****能构 层次网络 一定存在增广路***/
    {
        while(tf=dfs(1,INF))/****知道增量 为 0  表示 该层次网络没有曾广路了****/
        {
            flow+=tf;
        }
    }
    return flow;
}


int main()
{
    scanf("%d%d",&E,&V);
    memset(edge,0,sizeof(edge));
    while(E--)
    {
        int x,y,w;
        scanf("%d%d%d",&x,&y,&w);
        edge[x][y].cap+=w;//便于处理重边
    }
    S=1,T=V;
    printf("%d\n",dinic());
    return 0;
}


2、邻接表版(适用于顶点多的情况)
  • vector+ 边集数组实现(邻接表)(自己写的):

洛谷P3376

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e4+5;
int V, E, S, T;
int tot;
int level[maxn];

struct Edge
{
    int from, to;
    int cap;
    int flow;
};


vector<int>G[maxn];
vector<Edge>edge;
void init()
{
    for(int i = 0;i < V;i++)
    {
        G[i].clear();
    }

}
void input()
{
    int tot = 0;
    scanf("%d %d %d %d", &V, &E, &S, &T);
    init();
    while(E--)
    {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        Edge temp;
        temp.cap = w;
        temp.flow = 0;
        temp.from = u;
        temp.to  = v;
        edge.push_back(temp);
        G[u].push_back(tot++);
        temp.cap = 0; temp.from = v; temp.to = u;
        edge.push_back(temp);
        G[v].push_back(tot++);
    }

}
bool bfs()
{
    memset(level , 0 , sizeof(level));
    queue<int>q;
    level[S] = 1;
    q.push(S);

    int x;
    while(!q.empty())
    {
        x = q.front();
        q.pop();

        for(int i = 0;i < (int )G[x].size();i++)
        {
            int e = G[x][i];
            int y = edge[e].to;

            if(!level[y]&&edge[e].cap > edge[e].flow)
            {
                level[y] = level[x]+1;
                q.push(y);
            }
        }

    }

    return level[T] != 0;

}

int dfs(int x, int cp)
{
    if(x == T)
    {
        return cp;
    }

    int flow = cp;

    for(int i = 0;i <(int)G[x].size();i++)
    {
        int e = G[x][i];
        int y = edge[e].to;
        if(level[y] == level[x]+1 && edge[e].cap >edge[e].flow)
        {
            int minn = min(flow, edge[e].cap - edge[e].flow);

            int newflow = dfs(y, minn);
            flow-=newflow;
            edge[e].flow+=newflow;
            edge[e^1].flow-=newflow;

        }

    }


    return cp - flow;
}


int dinic()
{
    int flow = 0;
    int tf = 0;
    while(bfs())
    {
        while(tf = dfs(S, INF))
        {
            flow+=tf;
        }
    }
    return flow;
}





int main()
{



    input();
    int maxflow = dinic();

    printf("%d", maxflow);

    return 0;
}

  • 数组+边集数组(邻接表)
#include<bits/stdc++.h>
using namespace std;
const int maxn2 = 1e6+50;
const int maxn = 1e5;
const int INF = 0x3f3f3f;
int V, E, S, T;
int tot;
struct Edge/***表边****/
{
    int from, to;
    int cap, flow;
    int next;

}edge[maxn2];
int head[maxn]; /***表头**/

int level[maxn];

void init()
{
    memset(edge, 0, sizeof(edge));
    memset(head, -1, sizeof(head));
}

void add(int u, int v, int w)
{

    edge[tot].cap = w;
    edge[tot].from = u;
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
    edge[tot].cap = 0;
    edge[tot].from = v;
    edge[tot].to = u;
    edge[tot].next = head[v];
    head[v] = tot++;
}

void input()
{
    scanf("%d %d %d %d", &V, &E, &S, &T);
    tot = 0;
    while(E--)
    {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        add(u, v, w);
    }

}

bool bfs()
{
    memset(level, 0, sizeof(level));
    queue<int>q;
    level[S] = 1;
    q.push(S);

    int x;
    while(!q.empty())
    {
        x = q.front();
        q.pop();

        for(int i = head[x];i!= -1;i = edge[i].next)
        {
            int y = edge[i].to;
            if(!level[y]&& edge[i].cap > edge[i].flow)
            {
                level[y] = level[x]+1;
                q.push(y);
            }

        }

    }



    return level[T]!= 0;
}

int dfs(int x, int cp)
{
    if(x == T)return cp;

    int flow = cp;

    for(int i = head[x];i!= -1;i = edge[i].next)
    {
        int y = edge[i].to;
        if(level[y] == level[x]+1 && edge[i].cap > edge[i].flow)
        {
            int minn = min(flow, edge[i].cap - edge[i].flow);

            int newflow = dfs(y, minn);

            flow-= newflow;
            edge[i].flow+=newflow;
            edge[i^1].flow-=newflow;

        }

    }

    return cp - flow;
}

int dinic()
{
    int flow = 0;
    int tf = 0;
    while(bfs())
    {
        while(tf = dfs(S, INF))
        {
            flow+=tf;
        }
    }

    return flow;
}


int main()
{
    init();
    input();
    int maxflow = dinic();
    printf("%d", maxflow);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值