HDU1532 网络流最大流【EK算法】(模板题)

<题目链接>

题目大意:

一个农夫他家的农田每次下雨都会被淹,所以这个农夫就修建了排水系统,还聪明的给每个排水管道设置了最大流量;首先输入两个数n,m ;n为排水管道的数量,m为节点的数量,接下来就是n行数,每一行分为x1,x2,x3;x1,x2为节点的序号,x3为流量;然后问从1号节点到m号节点的最大流是多少?

解题分析:

网络流最大流裸题,下面用的是EK算法,bfs起搜索增广路径的作用,EK算法比较难理解的地方就是反向边的构造。

#include <cstdio>
#include <cmath>
#include <queue>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m;
int map1[205][205];
int pre[205];
int vis[205];
int s,t;

bool BFS()               //bfs搜索增广路径 
{
    int i,cur;
    queue<int>q;
    memset(pre,0,sizeof(pre));
    memset(vis,0,sizeof(vis));
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        if(cur==t)          
            return 1;            //如果搜索到终点,说明搜到一条增广路,return 1; 
        for(i=1; i<=n; i++)
        {
            if(!vis[i] &&map1[cur][i])
            {
                q.push(i);
                pre[i]=cur;       
                vis[i]=1;
            }
        }
    }
    return 0;            //没有搜到一条完整的增广路 
}

int Max_flow()
{
    int i,ans=0;
    while(1)
    {
        if(!BFS())      
            return ans;           //如果找不到增广路径了,此时ans算得的就是最大流 
            
        int Min=0x3f3f3f3f;
        for(i=t; i!=s; i=pre[i])     //遍历该条增广路径 
            Min=min(Min,map1[pre[i]][i]);      //找增广路径上的最小流量 
            
        for(i=t; i!=s; i=pre[i])
        {
            map1[pre[i]][i]-=Min;        //该条增广路径上的每条边都减去 min 
            map1[i][pre[i]]+=Min;        //该条增广路径上每条边修改反向边,反向边起到一种退流回溯的作用 
        }
        ans+=Min;
    }
}
int main()
{
    while(scanf("%d %d",&m,&n)!=EOF)
    {
        memset(map1,0,sizeof(map1));
        s=1,t=n;
        while(m--)
        {
            int u,v,c;
            scanf("%d%d%d",&u,&v,&c);
            map1[u][v]+=c;
        }
       printf("%d
",Max_flow());
    }
    return 0;
}

2018-08-14

原文地址:https://www.cnblogs.com/00isok/p/9474504.html