/*
Name: 最大流问题 ISAP 算法
Copyright:
Author: 巧若拙
Date: 13-06-17 14:30
Description:
*/
#include<iostream>
#include <fstream>
using namespace std;
const int MAXV=2000; //最大顶点数量
const int MAXE=2000; //最大边数量
const int INFINITY = 0x7fffffff; //无穷大
int capacity[MAXV][MAXV]; //记录残流网络的容量
//int flow[MAXV]; //标记从源点到当前节点实际还剩多少流量可用
int pre[MAXV]; //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int dis[MAXV]; //标记节点所在的层次
int gap[MAXV+1]; //标记某层结点的个数,判断是否出现断层
int counts = 0;
int MaxFlow_ISAP(int src, int des, int n) ;
bool BFS(int src, int des, int n); //广度优先搜索构造分层网络
int main()
{
int m, n, u, v;
ifstream fcin("maxflow.txt");
if (!fcin.is_open())
{
cout << "Error opening file"; exit (1);
}
fcin >> n >> m;
for(int i=0; i<m; ++i)
{
fcin >> u >> v;
fcin >> capacity[u][v];
}
cout << n << " " << m << endl;
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
{
cout << capacity[i][j] << " ";
}
cout << endl;
}
cout << MaxFlow_ISAP(0, n-1, n) << endl;
system("pause");
return 0;
}
int MaxFlow_ISAP(int src, int des, int n)
{
int inc, sumFlow = 0; //存储 src到des的最大流
int u, v, minLevel;
if (BFS(src, des, n))//先逆向构造分层网络
{
inc = INFINITY;
u = pre[src] = src;
while (dis[src] < n)
{
for (v=0; v<n; v++)
{
if (dis[u] == dis[v]+1 && capacity[u][v] != 0) //寻找下一层节点
{
break;
}
}
if (v < n)
{
pre[v] = u;
if (v == des)
{
inc = INFINITY;
for (int i=v; i!=src; i=pre[i])//计算最小增量
{
inc = (inc < capacity[pre[i]][i]) ? inc : capacity[pre[i]][i];
}
sumFlow += inc;
for (int i=v; i!=src; i=pre[i])//更新残流网络
{
capacity[pre[i]][i] -= inc;
capacity[i][pre[i]] += inc;
}
u = src; //返回源点
}
else //处理下层结点
{
u = v;
}
}
else //找不到可行弧
{
minLevel = n - 1;
for (v=0; v<n; v++)
{
if (capacity[u][v] != 0 && minLevel > dis[v]) //寻找下一层节点
{
minLevel = dis[v];
}
}
gap[dis[u]]--;
if (gap[dis[u]] == 0) //gap优化:出现断层即结束
{
break;
}
dis[u] = minLevel + 1; //如果是阻塞点,其高度为n
gap[dis[u]]++;
u = pre[u]; //返回上一层
}
}
}
return sumFlow;
}
bool BFS(int src, int des, int n)//逆向广度优先搜索构造分层网络,若不存在增广路,则返回false
{
int Queue[MAXV]; //求最短增广路算法需要用到的队列
int v, front = 0, rear = 0; //清空队列
for(int i=0; i<n; ++i) //初始化列表
{
dis[i] = 0;
gap[i] = 0;
pre[i] = -1;
}
//汇点加入队列
dis[des] = 1;
Queue[rear++] = des;
while (front < rear) //队列非空
{
v = Queue[front++];
for(int i=0; i<n; ++i) //寻找未访问过的邻接点,并设置层数
{
if (dis[i] == 0 && capacity[i][v] != 0)
{
dis[i] = dis[v] + 1;
gap[dis[i]]++;
Queue[rear++] = i;
}
}
}
return (dis[src] > 0); //能找到源点,说明存在增广路
}
最大流问题 ISAP 算法
最新推荐文章于 2022-12-01 08:52:08 发布