最大流问题预流推进算法(最基本)

/*
  Name: 最大流问题预流推进算法
  Copyright: 
  Author: 巧若拙 
  Date: 14-06-17 09:26
  Description: 最基本的预流推进算法,没有任何优化,每次遍历所有的结点,找出活结点,
  寻找可行弧,并预流推进,若没有可以push的顶点,执行relabel操作。 
*/
#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 dis[MAXV]; //标记节点所在的层次    

int counts = 0;
    
int MaxFlow_push_relabel(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_push_relabel(0, n-1, n) << endl;    
    
    system("pause");                       
    return 0;    
}    
    
int MaxFlow_push_relabel(int src, int des, int n)    
{         
    int u, v, minLevel, minFlow;  
	bool done = true, relabel = true;  
    
    dis[src] = n;  //直接设源点高度为n 
    for (v = 0; v < n; v++) //将源点的流量推进到邻接点 
    {  
        if (capacity[src][v] > 0) //更新结点剩余流量和残流网络 
        {  
            flow[src] -= capacity[src][v];  
            flow[v] = capacity[src][v];  
            capacity[v][src] = capacity[src][v];  
            capacity[src][v] = 0; 
        }  
    }   
    
    while (1)
    {
        done = true;  
        for (u=0; u<n; u++)
        {
            if (u != src && u != des && flow[u] > 0) //寻找活结点 
            {
                done = false;  
                relabel = true;   //先假设顶点u需要relabel  
                for (v=0; v<n; v++)
                {
                    if (dis[u] == dis[v]+1 && capacity[u][v] > 0) //寻找可行弧,并预流推进 
                    {
                        relabel = false;  
                        minFlow = (flow[u] < capacity[u][v]) ? flow[u] : capacity[u][v];	   
                        flow[u] -= minFlow;  
                        flow[v] += minFlow;  
                        capacity[u][v] -= minFlow;  
                        capacity[v][u] += minFlow; 
                        printf("push %d --%d--> %d, e[%d] = %d\n", u, minFlow, v, u, flow[u]);  
                        if (flow[u] == 0) //无剩余流量了就停止搜索可行弧 
                        {
                            break;
                        }
                    }
                }
                //没有可以push的顶点,执行relabel 
                if (relabel) 
                {   
                    minLevel = INFINITY; 
                    for (v=0; v<n; v++)
                    {
                        if (capacity[u][v] > 0 && minLevel > dis[v]) //寻找下一层节点的最小层高 
                        {
                            minLevel = dis[v];
                        } 
                    }
                    dis[u] = minLevel + 1;
                    printf("relabel %d height to %d\n", u, dis[u]); 
                }  
            }
        }
        if (done) //已经没有活结点了,操作结束 
        { 
            return flow[des];    
        }  
    } 
}    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值