最大流问题 ISAP 算法

/*
  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); //能找到源点,说明存在增广路 
}    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值