单源点单汇点的最大流算法,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;
}