mirror of
https://github.com/Hizenberg469/Algorithms-snippets.git
synced 2026-04-19 22:52:23 +03:00
added Advanced Graph Algorithm
This commit is contained in:
183
Advanced Graph Algorithm/Ford_Fulkerson.cpp
Normal file
183
Advanced Graph Algorithm/Ford_Fulkerson.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
//used for ignoring/removing the assert statement at compile-time.
|
||||
//#define NDEBUG
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Edge{
|
||||
public:
|
||||
int from, to;
|
||||
Edge* residual;
|
||||
long flow;
|
||||
long capacity;
|
||||
|
||||
Edge(int from, int to, long capacity){
|
||||
this->from = from;
|
||||
this->to = to;
|
||||
this->capacity = capacity;
|
||||
flow = 0;
|
||||
}
|
||||
|
||||
bool isResidual(){
|
||||
return capacity == 0;
|
||||
}
|
||||
|
||||
long remainingCapacity(){
|
||||
return capacity - flow;
|
||||
}
|
||||
|
||||
void augment(long bottleNeck){
|
||||
flow += bottleNeck;
|
||||
residual->flow -= bottleNeck;
|
||||
}
|
||||
|
||||
string toString(int s ,int t){
|
||||
string u = (from == s) ? "s" : ((from == t) ? "t" : to_string(from));
|
||||
string v = (to == s ) ? "s" : ((to == t) ? "t" : to_string(to));
|
||||
string res = "Edge " + u + " -> " + v + " | " + " flow = " +
|
||||
to_string(flow) + " | " + " capacity: " + to_string(capacity)
|
||||
+ " | " + " is residual: " + to_string((int)isResidual()) ;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
class NetworkFlowSolverBase{
|
||||
protected :
|
||||
long INF = INT_MAX/2;
|
||||
//Input: n = Number of nodes, s = source, t = sink
|
||||
int n , s, t;
|
||||
|
||||
//'visited' and 'visitedToken' are keep track of the
|
||||
//visited nodes.
|
||||
protected:
|
||||
int visitedToken = 1;
|
||||
int* visited;
|
||||
|
||||
|
||||
bool solved;
|
||||
long maxFlow;
|
||||
|
||||
//Representing the graph.
|
||||
vector<vector<Edge*>> graph;
|
||||
|
||||
public:
|
||||
|
||||
NetworkFlowSolverBase(int n, int s,int t){
|
||||
this->n = n;
|
||||
this->s = s;
|
||||
this->t = t;
|
||||
graph.resize(n);
|
||||
visited = new int[n];
|
||||
}
|
||||
|
||||
void addEdge(int from ,int to ,long capacity){
|
||||
assert(capacity > 0);
|
||||
|
||||
Edge* e1 = new Edge(from, to , capacity);
|
||||
Edge* e2 = new Edge(to, from, 0);
|
||||
e1->residual = e2;
|
||||
e2->residual = e1;
|
||||
graph[from].push_back(e1);
|
||||
graph[to].push_back(e2);
|
||||
}
|
||||
|
||||
vector<vector<Edge*>> getGraph(){
|
||||
execute();
|
||||
return graph;
|
||||
}
|
||||
|
||||
long getMaxFlow(){
|
||||
execute();
|
||||
return maxFlow;
|
||||
}
|
||||
|
||||
private :
|
||||
void execute(){
|
||||
if( solved )return;
|
||||
solved = true;
|
||||
solve();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void solve(){}
|
||||
};
|
||||
|
||||
|
||||
class FordFulkersonDfsSolver : public NetworkFlowSolverBase{
|
||||
public :
|
||||
FordFulkersonDfsSolver(int n, int s, int t) : NetworkFlowSolverBase(n,s,t){
|
||||
}
|
||||
|
||||
void solve(){
|
||||
for( long f = dfs(s, INF) ; f != 0 ; f = dfs(s,INF)){
|
||||
visitedToken++;
|
||||
maxFlow += f;
|
||||
}
|
||||
}
|
||||
|
||||
private :
|
||||
long dfs(int node, long flow){
|
||||
if( node == t )return flow;
|
||||
|
||||
visited[node] = visitedToken;
|
||||
|
||||
vector<Edge*> edges = graph[node];
|
||||
for(Edge* edge : edges){
|
||||
if( edge->remainingCapacity() > 0 && visited[edge->to] != visitedToken){
|
||||
long bottleNeck = dfs(edge->to , min(flow,edge->remainingCapacity()));
|
||||
|
||||
if( bottleNeck > 0){
|
||||
edge->augment(bottleNeck);
|
||||
return bottleNeck;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(){
|
||||
|
||||
int n = 12;
|
||||
|
||||
int s = n - 2;
|
||||
int t = n - 1;
|
||||
|
||||
NetworkFlowSolverBase* solver = new FordFulkersonDfsSolver(n,s,t);
|
||||
|
||||
//Edges from Source
|
||||
solver->addEdge(s, 0, 10);
|
||||
solver->addEdge(s, 1, 5);
|
||||
solver->addEdge(s, 2, 10);
|
||||
|
||||
//Middle edges
|
||||
solver->addEdge(0, 3, 10);
|
||||
solver->addEdge(1, 2, 10);
|
||||
solver->addEdge(2, 5, 15);
|
||||
solver->addEdge(3, 1, 2);
|
||||
solver->addEdge(3, 6, 15);
|
||||
solver->addEdge(4, 1, 15);
|
||||
solver->addEdge(4, 3, 3);
|
||||
solver->addEdge(5, 4, 4);
|
||||
solver->addEdge(5, 8, 10);
|
||||
solver->addEdge(6, 7, 10);
|
||||
solver->addEdge(7, 4, 10);
|
||||
solver->addEdge(7, 5, 7);
|
||||
|
||||
//Edges to sink
|
||||
solver->addEdge(6, t, 15);
|
||||
solver->addEdge(8, t, 10);
|
||||
|
||||
cout << "Maximum Flow is: " << solver->getMaxFlow() << '\n';
|
||||
|
||||
vector<vector<Edge*>> resultGraph = solver->getGraph();
|
||||
|
||||
for(vector<Edge*> edges : resultGraph ){
|
||||
for( Edge* e : edges){
|
||||
cout << e->toString(s,t) << '\n';
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user