Skip to content

Commit aeb63f5

Browse files
committedJun 14, 2017
Maximum Flow using Edmond Karp second implementation added
Maximum Bipartite matching using Edmond Karp maximum flow algorithm implemented
1 parent ac27548 commit aeb63f5

File tree

3 files changed

+171
-1
lines changed

3 files changed

+171
-1
lines changed
 

‎README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@
5656
+ [Bellman Ford's](algorithms/bellman_fords.cpp)
5757
+ [Kruskal Minimum Spanning Tree](algorithms/kruskal.cpp)
5858
+ [Minimum Vertex Cover](algorithms/min_vertex_cover.cpp)
59-
+ [Maximum Flow (Edmonds Karp’s)](algorithms/max_flow.cpp)
59+
+ [Maximum Flow (Edmonds Karp’s) I](algorithms/max_flow.cpp)
60+
+ [Maximum Flow (Edmonds Karp’s) II](algorithms/Maximum_Flow_Problem_I_Edmond_Karp.cpp)
61+
+ [Maximum Bipartite Matching](algorithms/maximum_bipartite_matching.cpp)
6062
+ [Stable Marriage Problem](algorithms/stable_marriage_problem.cpp)
6163
+ [Heavy Light Decomposition](algorithms/HLD.cpp)
6264

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Ford-Fulkerson + Edmond Karp algorithm
2+
// single source - single sink maximum flow
3+
#define MAX 1005
4+
5+
vector<pair<int, int>> adj[MAX]; // adj[u] = {{v1, capacity1}, {v2, capacity2}}
6+
vector<int> residual[MAX]; // residual[u][v1] = capacity1
7+
int parent[MAX];
8+
bool visited[MAX];
9+
int n;
10+
11+
/* Returns true if there is a path from 'src' to 'sink' in
12+
residual graph. Also fills parent[] to store the path */
13+
bool bfs(int src, int sink) {
14+
memset(visited, false, sizeof visited);
15+
queue <int> q;
16+
q.push(src);
17+
visited[src] = true;
18+
parent[src] = -1;
19+
20+
while (!q.empty()) {
21+
int u = q.front();
22+
q.pop();
23+
for(int i = 0; i < (int)adj[u].size(); i++) {
24+
int v = adj[u][i].first;
25+
if(!visited[v] and residual[u][v] > 0) {
26+
q.push(v);
27+
parent[v] = u;
28+
visited[v] = true;
29+
}
30+
}
31+
}
32+
33+
// If we reached sink in BFS starting from source, then return true, else false
34+
return visited[sink];
35+
}
36+
37+
int edmondKarp(int src, int sink) {
38+
int maxFlow = 0;
39+
for(int u = 0; u < n; u++) {
40+
for(int i = 0; i < (int)adj[u].size(); i++) {
41+
int v = adj[u][i].first;
42+
int capacity = adj[u][i].second;
43+
residual[u][v] = capacity;
44+
}
45+
}
46+
while(bfs(src, sink)) {
47+
int pathFlow = INT_MAX;
48+
// trace augmenting path
49+
int v = sink;
50+
while(v != src) {
51+
int u = parent[v];
52+
pathFlow = min(pathFlow, residual[u][v]);
53+
v = u;
54+
}
55+
56+
// update residual graph
57+
v = sink;
58+
while(v != src) {
59+
int u = parent[v];
60+
residual[u][v] -= pathFlow;
61+
residual[v][u] += pathFlow;
62+
v = u;
63+
}
64+
65+
maxFlow += pathFlow;
66+
}
67+
68+
return maxFlow;
69+
}
+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Maximum Bipartite matching using Edmond Karp maximum flow problem
2+
#define MAX 1005
3+
4+
vector<pair<int, int>> adj[MAX]; // adj[u] = {{v1, capacity1}, {v2, capacity2}}
5+
vector<int> residual[MAX]; // residual[u][v1] = capacity1
6+
int parent[MAX];
7+
bool visited[MAX];
8+
int n;
9+
10+
/* Returns true if there is a path from 'src' to 'sink' in
11+
residual graph. Also fills parent[] to store the path */
12+
bool bfs(int src, int sink) {
13+
memset(visited, false, sizeof visited);
14+
queue <int> q;
15+
q.push(src);
16+
visited[src] = true;
17+
parent[src] = -1;
18+
19+
while (!q.empty()) {
20+
int u = q.front();
21+
q.pop();
22+
for(int i = 0; i < (int)adj[u].size(); i++) {
23+
int v = adj[u][i].first;
24+
if(!visited[v] and residual[u][v] > 0) {
25+
q.push(v);
26+
parent[v] = u;
27+
visited[v] = true;
28+
}
29+
}
30+
}
31+
32+
// If we reached sink in BFS starting from source, then return true, else false
33+
return visited[sink];
34+
}
35+
36+
int edmondKarp(int src, int sink) {
37+
int maxFlow = 0;
38+
for(int u = 0; u < n; u++) {
39+
residual[u].resize(n);
40+
for(int i = 0; i < (int)adj[u].size(); i++) {
41+
int v = adj[u][i].first;
42+
int capacity = adj[u][i].second;
43+
residual[u][v] = capacity;
44+
}
45+
}
46+
while(bfs(src, sink)) {
47+
int pathFlow = INT_MAX;
48+
// trace augmenting path
49+
int v = sink;
50+
while(v != src) {
51+
int u = parent[v];
52+
pathFlow = min(pathFlow, residual[u][v]);
53+
v = u;
54+
}
55+
56+
// update residual graph
57+
v = sink;
58+
while(v != src) {
59+
int u = parent[v];
60+
residual[u][v] -= pathFlow;
61+
residual[v][u] += pathFlow;
62+
v = u;
63+
}
64+
65+
maxFlow += pathFlow;
66+
}
67+
68+
return maxFlow;
69+
}
70+
71+
/*
72+
There are M job applicants and N jobs. Each applicant has a subset of jobs that he/she is interested in.
73+
Each job opening can only accept one applicant and a job applicant can be appointed for only one job.
74+
Find an assignment of jobs to applicants in such that as many applicants as possible get jobs.
75+
*/
76+
// Create a flow network before where there is an edge with capacity 1 from each applicants to
77+
// to each of his/her preferred jobs
78+
// i.e. adj[i].push_back({j, 1})
79+
int maxBPM(int N, int M) {
80+
// create two new nodes 'src' and 'sink'
81+
int src = N + M;
82+
int sink = N + M + 1;
83+
84+
// total nodes = total nodes of bipartite graph + two extra nodes(source and sink)
85+
n = N + M + 2;
86+
87+
// add edge with capacity of 1 unit from src to each applicants node
88+
for(int i = 0; i < N; i++) {
89+
adj[src].push_back({i, 1});
90+
}
91+
92+
// add edge with capacity of 1 unit from each jobs node to sink
93+
for(int i = N; i < N + M; i++) {
94+
adj[i].push_back({sink, 1});
95+
}
96+
97+
// Now the maximum flow from src to sink is the maximum matching of bipartite graph
98+
return edmondKarp(src, sink);
99+
}

0 commit comments

Comments
 (0)
Please sign in to comment.