// graph.cpp -- implement file.
// 2011-09-25-14.31 -- 2011-09-25-15.58
// 2011-09-25-18.16 -- 2011-09-25-20.00
// 2011-09-26-17.20 -- 2011-09-26-18.04
// 2011-09-26-19.19 -- 2011-09-26-20.00
// 2011-09-27-09.06 -- 2011-09-27-09.57
template<class T>
void Graph<T> ::getIncreasingOrder (unsigned int currentIndex)
{
static T * duplicateOfResidualFlowOfALine = new T[m_totalNumOfVertexes] ;
// Initialize duplicateOfResidualFlowOfALine.
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
duplicateOfResidualFlowOfALine[i] = m_residualFlow[currentIndex][i] ;
}
// Initialize m_currentVertexAdjoinsTo in normal order.
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
m_currentVertexAdjoinsTo[i] = i ;
}
// Sorting duplicateOfResidualFlowOfALine in increasing order.
// As a result of, m_currentVertexAdjoinsTo will be sorted as duplicateOfResidualFlowOfALine in increasing order.
unsigned int i = 1 ;
while (i < m_totalNumOfVertexes)
{
T tempResidual = duplicateOfResidualFlowOfALine[i] ;
unsigned int tempVertex = m_currentVertexAdjoinsTo[i] ;
unsigned int j = i ;
while (j != 0 && tempResidual < duplicateOfResidualFlowOfALine[j - 1])
{
duplicateOfResidualFlowOfALine[j] = duplicateOfResidualFlowOfALine[j - 1] ;
m_currentVertexAdjoinsTo[j] = m_currentVertexAdjoinsTo[j - 1] ;
--j ;
}
duplicateOfResidualFlowOfALine[j] = tempResidual ;
m_currentVertexAdjoinsTo[j] = tempVertex ;
++i ;
}
}
template<class T>
bool Graph<T> ::m_existsAAugmentingPath (T * const pMinFlows)
{
m_color[m_startIndex] = Color_Gray ;
m_parent[m_startIndex] = HasNotAParent ;
queue<int> q ;
q.push(m_startIndex) ;
T minFlow = Infinity ;
while (!q.empty())
{
unsigned int topIndex = q.front() ;
// After called getIncreasingOrder(topIndex), m_currentVertexAdjoinsTo[] will be sorted.
// m_currentVertexAdjoinsTo[0] <= m_currentVertexAdjoinsTo[1] <= ... <= m_currentVertexAdjoinsTo[m_totalNumOfVertexes - 1].
// So will select a shortest path every time, this is very important for this algorithm.
getIncreasingOrder(topIndex) ;
q.pop() ;
for (unsigned int index = 0; index < m_totalNumOfVertexes; ++index)
{
if (Color_White == m_color[m_currentVertexAdjoinsTo[index]] && m_residualFlow[topIndex][m_currentVertexAdjoinsTo[index]] > 0)
{
if (m_residualFlow[topIndex][m_currentVertexAdjoinsTo[index]] < minFlow)
{
minFlow = m_residualFlow[topIndex][m_currentVertexAdjoinsTo[index]] ;
}
m_parent[m_currentVertexAdjoinsTo[index]] = topIndex ;
m_color[m_currentVertexAdjoinsTo[index]] = Color_Gray ;
q.push(m_currentVertexAdjoinsTo[index]) ;
}
}
m_color[topIndex] = Color_Black ;
}
// Record the min flow.
*pMinFlows = minFlow ;
// Test if has visited V[endIndex], if so mean there exists a path from V[startIndex] to V[endIndex] in the residual net.
if (Color_Black == m_color[m_endIndex])
return true ;
else
return false ;
}
// Start index must be 0 and end index must be numOfVertexes - 1.
template<class T>
Graph<T> ::Graph (unsigned int numOfVertexes):
m_selectedFlow(NULL),
m_residualFlow(NULL),
m_currentVertexAdjoinsTo(NULL),
m_color(NULL),
m_currentNumOfVertexes(0),
m_totalNumOfVertexes(numOfVertexes),
HasNotAParent(numOfVertexes + 1),
m_startIndex(0),
m_endIndex(numOfVertexes - 1)
{
if (0 == numOfVertexes)
throw std ::runtime_error("Empty graph is invalid.") ;
// Allocate memory and initialize elements.
m_selectedFlow = new T *[numOfVertexes] ;
for (unsigned int i = 0; i < numOfVertexes; ++i)
{
m_selectedFlow[i] = new T[numOfVertexes] ;
}
for (unsigned int i = 0; i < numOfVertexes; ++i)
{
for (unsigned int j = 0; j < numOfVertexes; ++j)
{
m_selectedFlow[i][j] = 0 ;
}
}
m_residualFlow = new T*[numOfVertexes] ;
for (unsigned int i = 0; i < numOfVertexes; ++i)
{
m_residualFlow[i] = new T[numOfVertexes] ;
}
for (unsigned int i = 0; i < numOfVertexes; ++i)
{
for (unsigned int j = 0; j < numOfVertexes; ++j)
{
m_residualFlow[i][j] = 0 ;
}
}
// Initialize m_currentVertexAdjoinsTo at runtime.
m_currentVertexAdjoinsTo = new unsigned int[numOfVertexes] ;
m_color = new Color[numOfVertexes] ;
for (unsigned int i = 0; i < numOfVertexes; ++i)
{
m_color[i] = Color_White ;
}
m_parent = new unsigned int[numOfVertexes] ;
for (unsigned int i = 0; i < numOfVertexes; ++i)
{
m_parent[i] = HasNotAParent ;
}
}
template<class T>
bool Graph<T> :: importAVertex(
const vector<T> &indexAdjoinsTo,
const vector<T> &residualFlowAdjoinsTo)
{
if (m_currentNumOfVertexes == m_totalNumOfVertexes || indexAdjoinsTo.size() != residualFlowAdjoinsTo.size())
return false ;
vector<T> ::const_iterator iterIndex = indexAdjoinsTo.begin() ;
vector<T> ::const_iterator iterResidual = residualFlowAdjoinsTo.begin() ;
while (iterIndex != indexAdjoinsTo.end())
{
m_residualFlow[m_currentNumOfVertexes][*iterIndex] = *iterResidual ;
// Its reversed edge's residual flow had been setted as 0 when ctor was calling.
++iterIndex ;
++iterResidual ;
}
++m_currentNumOfVertexes ;
return true ;
}
template<class T>
void Graph<T> ::calculateMaxFlow (void)
{
T minFlow ;
while (m_existsAAugmentingPath(&minFlow))
{
// There exists a path from V[startIndex] to V[endIndex] in the residual net.
// Updata m_selectedFlow and m_residualFlow along breadth first search path.
unsigned int currentIndex = m_endIndex ;
unsigned int parentIndex = m_parent[m_endIndex] ;
while (parentIndex != HasNotAParent)
{
m_selectedFlow[parentIndex][currentIndex] += minFlow ;
m_residualFlow[parentIndex][currentIndex] -= minFlow ;
m_residualFlow[currentIndex][parentIndex] += minFlow ;
currentIndex = parentIndex ;
parentIndex = m_parent[currentIndex] ;
}
// Reset parentIndex and m_color for next calling.
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
m_parent[i] = HasNotAParent ;
}
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
m_color[i] = Color_White ;
}
}
}
template<class T>
T Graph<T> ::maxFlow (void) const
{
// Calculate all the flows start from V[startIndex], it's the flows between startIndex and endIndex.
T flows = 0 ;
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
// If there isn't a path between V[startIndex] and V[i],
// m_selectedFlow[startIndex][i] is 0.
flows += m_selectedFlow[m_startIndex][i] ;
}
return flows ;
}
template<class T>
void Graph<T> ::printEveryFlow (void) const
{
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
for (unsigned int j = 0; j < m_totalNumOfVertexes; ++j)
{
if (m_selectedFlow[i][j] > 0)
{
std ::cout << "V[" << i << "] ->[" << j << "]: " << m_selectedFlow[i][j] << std ::endl ;
}
}
}
}
template<class T>
void Graph<T> ::printGraph (void) const
{
if (m_currentNumOfVertexes < m_totalNumOfVertexes)
{
std ::cout << "Not all vertexes have been inported, can't print the graph." ;
return ;
}
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
for (unsigned int j = 0; j < m_totalNumOfVertexes; ++j)
{
std ::cout << m_selectedFlow[i][j] << " " ;
}
std ::cout << std ::endl ;
}
for (unsigned int i = 0; i < m_totalNumOfVertexes; ++i)
{
for (unsigned int j = 0; j < m_totalNumOfVertexes; ++j)
{
std ::cout << m_residualFlow[i][j] << " " ;
}
std ::cout << std ::endl ;
}
}
最大流Edmonds-Karp算法实现文件C++
最新推荐文章于 2019-04-29 20:04:29 发布