最大流算法

单源点单汇点的最大流算法,C++实现例子一枚。

/*
 * Graph.cpp
 *
 *  Created on: 2013-1-18
 *      Author: qichi
 */

#include "Graph.h"
#include <string.h>
#include <iostream>

/*
 * DAG
 */
Graph::Graph(int n, int s, int t) {

	m_nVertex = n;
	m_nStart = s;
	m_nTarget = t;
	m_nMaxFlow = 0;

	m_pEdges = new EDGE*[n];
	m_bVisited = new bool[n];
	m_pStack = new int[n];
	m_nTop = -1;

	// allocate continuous memory for 2-d array
	m_pMatrix = new double*[n];
	m_pMatrix[0] = new double[n*n];
	for ( int i=1; i<n; i++ ) {
		m_pMatrix[i] = m_pMatrix[i-1]+n;
	}

	// initialize arrays
	memset(m_pEdges,0,n*sizeof(EDGE*));
	memset(m_pMatrix[0],0,n*n*sizeof(double));
	memset(m_pStack,0,n*sizeof(int));

}

Graph::~Graph() {
	for ( int i=0; i<m_nVertex; i++ ) {
		EDGE *e= m_pEdges[i];
		while ( e ) {
			EDGE *p = e;
			e = e->next;
			delete p;
		}
	}
	delete m_pEdges;
	delete m_pMatrix[0];
	delete m_pMatrix;
	delete m_bVisited;
}

void Graph::insert(int i, int j, double volume, double price) {

	// insert an edge
	EDGE *e = new EDGE();
	e->target = j;
	e->volum = volume;
	e->price = price;
	e->next = m_pEdges[i];
	m_pEdges[i] = e;

	// insert a reverse edge
	e = new EDGE();
	e->target = i;
	e->volum = 0;
	e->price = price;
	e->next = m_pEdges[j];
	m_pEdges[j] = e;

	// insert it to matrix
	m_pMatrix[i][j] = volume;

}

void Graph::print() {
	std::cout << "Adjacent matrix of graph : " << std::endl;
	for ( int i=0; i<m_nVertex; i++ ) {
		for ( int j=0; j<m_nVertex; j++ ) {
			std::cout << m_pMatrix[i][j] << " ";
		}
		std::cout << std::endl;
	}
}

bool Graph::explore(int u, int t) {
	m_pStack[++m_nTop] = u;
	m_bVisited[u] = true;
	bool res = false;
	if ( u == t ) {
		// search max flow allowed on path
		double maxv = 1.0e+32;
		for ( int i=0; i<m_nTop; i++ ) {
			int x=m_pStack[i], y=m_pStack[i+1];
			if ( m_pMatrix[x][y] < maxv )
				maxv = m_pMatrix[x][y];
		}
		// reduce volume of edges along through path
		for ( int i=0; i<m_nTop; i++ ) {
			int x=m_pStack[i], y=m_pStack[i+1];
			m_pMatrix[x][y] -= maxv;
			m_pMatrix[y][x] += maxv;
		}
		// add to max flow
		m_nMaxFlow += maxv;
		res = true;
	} else {
		EDGE *e = m_pEdges[u];
		while ( e!=NULL ) {
			int v = e->target;
			// v is not visited && <u,v> has extra volume
			if ( ! m_bVisited[v] && m_pMatrix[u][v] > 0 ) {
				res = explore(v, t);
				if ( res ) break;
			}
			e = e->next;
		}
	}
	m_nTop--;
	return res;
}

void Graph::maxflow() {

	bool res = false;
	do {
		for ( int i=0; i<m_nVertex; i++ ) {
			m_bVisited[i] = false;
		}
		m_nTop = -1;
		res = explore(m_nStart,m_nTarget);
	} while ( res );

	// show the max flow and flow on each edge
	std::cout << "Max flow is : " << m_nMaxFlow << std::endl;
	for ( int i=0; i<m_nVertex; i++ ) {
		EDGE *e=m_pEdges[i];
		while ( e ) {
			if ( e->volum > 0 ) {
				int j = e->target;
				std::cout << "Flow on edge <" << i << "," << j ;
				std::cout << "> is " << e->volum - m_pMatrix[i][j] << std:: endl;
			}
			e = e->next;
		}
	}

}

/*
 * Graph.h
 *
 *  Created on: 2013-1-18
 *      Author: qichi
 */

#ifndef GRAPH_H_
#define GRAPH_H_

typedef struct EDGE {
	double volum;
	double price;
	int target;
	EDGE *next;
} EDGE ;

class Graph {
private:

	// link of edges
	int m_nVertex;
	EDGE **m_pEdges;

	// adjacent matrix of volume
	double **m_pMatrix;

	// a stack to save path
	int 	*m_pStack;
	int		m_nTop;

	// a array to mark visited vertex
	bool	*m_bVisited;

	// max flow
	int m_nStart;
	int m_nTarget;
	int m_nMaxFlow;

public:
	Graph(int n, int s, int t);
	virtual ~Graph();
	void insert(int i, int j, double volume, double price);
	void print();
	bool explore(int s, int t);
	void maxflow();
};

#endif /* GRAPH_H_ */

//============================================================================
// Name        : MaxFlowProblem.cpp
// Author      : Qichi
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include "Graph.h"
using namespace std;

int main() {

	int n, s, t;
	cout << "Enter number of vertex <n s t>: ";
	cin >> n >> s >> t;

	if ( n <= 0 ) {
		cout << "Invalid number!" << endl;
		return 1;
	}

	Graph *g = new Graph(n, s, t);

	int i, j;
	double v, p;
	cout << "Enter an edge <i j v p > : ";
	while ( cin >> i >> j >> v >> p ) {
		g->insert(i,j,v,p);
		cout << "Enter an edge <i j v p > : ";
	}
	cout << endl;

	g->maxflow();

	delete g;
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值