-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathSTCutFordFulkersonBased.cs
More file actions
118 lines (91 loc) · 3.44 KB
/
STCutFordFulkersonBased.cs
File metadata and controls
118 lines (91 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System;
using System.Collections.Generic;
namespace AlgorithmsAndDataStructures.Algorithms.Graph.MaximumFlow;
public class StCutFordFulkersonBased
{
#pragma warning disable CA1822 // Mark members as static
public List<Tuple<int, int>> GetStCut(int[][] graph)
#pragma warning restore CA1822 // Mark members as static
{
if (graph is null) return new List<Tuple<int, int>>(0);
var residualGraph = new int[graph.Length][];
for (var i = 0; i < residualGraph.Length; i++)
{
residualGraph[i] = new int[graph.Length];
for (var j = 0; j < graph.Length; j++) residualGraph[i][j] = graph[i][j];
}
bool hasPath;
var targetVertex = graph.Length - 1;
do
{
var path = GetBfsPath(residualGraph, targetVertex);
hasPath = path != null;
if (hasPath)
{
var delta = GetDelta(path, residualGraph, targetVertex);
var currentVertex = graph.Length - 1;
var parent = path[currentVertex];
while (parent >= 0)
{
residualGraph[parent][currentVertex] = residualGraph[parent][currentVertex] - delta;
residualGraph[currentVertex][parent] = residualGraph[currentVertex][parent] + delta;
currentVertex = parent;
parent = path[currentVertex];
}
}
} while (hasPath);
var visited = new bool[graph.Length];
Dfs(0, residualGraph, visited);
var result = new List<Tuple<int, int>>();
for (var i = 0; i < graph.Length; i++)
{
var currentVertex = graph[i];
for (var j = 0; j < graph.Length; j++)
if (currentVertex[j] > 0 && visited[i] && !visited[j])
result.Add(new Tuple<int, int>(i, j));
}
return result;
}
private static void Dfs(int v, IReadOnlyList<int[]> residualGraph, IList<bool> visited)
{
visited[v] = true;
for (var i = 0; i < residualGraph[v].Length; i++)
if (!visited[i] && residualGraph[v][i] > 0)
Dfs(i, residualGraph, visited);
}
private static int GetDelta(IReadOnlyList<int> path, IReadOnlyList<int[]> residualGraph, int targetVertex)
{
var delta = int.MaxValue;
var currentVertex = targetVertex;
var parent = path[currentVertex];
while (parent >= 0)
{
delta = Math.Min(residualGraph[parent][currentVertex], delta);
currentVertex = parent;
parent = path[currentVertex];
}
return delta;
}
private static int[] GetBfsPath(IReadOnlyList<int[]> residualGraph, int targetVertex)
{
var queue = new Queue<int>();
var visited = new bool[residualGraph.Count];
var path = new int[residualGraph.Count];
visited[0] = true;
path[0] = -1;
queue.Enqueue(0);
while (queue.Count > 0)
{
var currentVertex = queue.Dequeue();
for (var i = 0; i < residualGraph[currentVertex].Length; i++)
if (!visited[i] && residualGraph[currentVertex][i] > 0)
{
path[i] = currentVertex;
visited[i] = true;
if (i == targetVertex) return path;
queue.Enqueue(i);
}
}
return null;
}
}