本人初学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;
}