Ford-Fulkerson方法计算网络最大流问题(简洁易懂,新手入门)

本人初学C++,解决一下这个简单的网络最大流问题(弱鸡的我看了一晚上才看懂咋回事),

算法的核心就在于每一次找到增广路径之后都要给正向边减去当前最大流,而反向边加上这个值,使得流守恒,

通过DFS的方法我们就可以找到最大流啦。不过FF算法的时间效率较低,建议看懂这个之后再去看看EK方法和其他算法。

注:在VS2015下运行通过(代码80行)



#include<iostream>

using namespace std;
#define MAX  100
#define INF    100000000
int map[MAX][MAX];    //领接矩阵,残留网络
int vis[MAX];        //是否访问
int n, m,s,t;            //点的个数,边的个数
int total = 0;        //最大流
int path[MAX];

int min(int f, int d) //比较两数大小
{
    if (f > d) return d;
    else return f;
}
int dfs(int i, int j,int g) //找[一条]增广路,并返回最大流,i为当前标号,j为当前最小割(最大流),g为当前路径的第g个节点
{
    path[g] = i;       //先把路径记录下来
    if (i == t)         //如果到边界就返回最小割
        return j;
    else
    {
        int h = 0;
        for ( h = 0; h < n; h++) //找后继节点
        {
            if (!vis[h] && map[i][h] > 0)    //未访问过且有增广路经
            {
                vis[h] = 1;                  //找到一个节点,打上标记
                int ans = dfs(h, min(j, map[i][h]), g + 1); //继续找
                if (ans > 0) return ans;          //如果找到的最小割大于0就返回最大流
                else continue;
            }
        }
        if (h == n) return 0; //没找到,返回0
    }
}
int size(int a[])                        //返回数组长度
{
    for (int i = 0; i < MAX; i++){
        if (a[i] == -1) return i;
    }
    return MAX;
}
int Ford_Fulkerson(int s, int t)        //起点和终点
{
    int u = 0;
    while (1)
    {
        memset(path, -1, sizeof(path)); //路径数组初始化
        memset(vis, 0, sizeof(vis));    //是否访问过
        u = dfs(s, INF, 0);
        if (u == 0)  break;
        else
        {
            for (int i = 0; i < size(path)-1; i++) //增加反向边
            {
                map[path[i]][path[i + 1]] -= u;
                map[path[i + 1]][path[i]] += u;
            }
            total += u;
        }
    }
    return total; //返回最大流
}
int main()
{
    memset(map, 0, sizeof(map));
    cout << "注意,点的标号从0开始" << endl;
    int a, b, weight;
    cin >> n >> m >> s >> t;      //点的个数,边的个数,起点,终点
    for (int i = 0; i < m; i++)
    {
        cin >> a >> b>>weight;  //weight为边的权重
        map[a][b] = weight;
    }
    int answer = Ford_Fulkerson(s, t);
    cout << "最大流为: "<<answer<<endl;
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值