-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathditch.java
147 lines (132 loc) · 4.02 KB
/
ditch.java
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
/*
ID: Xu Yan
LANG: JAVA
TASK: ditch
*/
/**
* Thoughts: Use Ford-Fulkerson Algorithm to find max-flow
* Pitfalls:
*
* Take-away tips:
*
* @author Xu Yan
* @date October 15th, 2016
*/
public class ditch {
private static class FlowGraph {
private final Map<Integer, List<FlowEdge>> graph;
private int intersection_count;
private FlowEdge[] aug_path;
public FlowGraph(int intersection_count) {
this.graph = new HashMap<Integer, List<FlowEdge>>();
this.intersection_count = intersection_count;
this.aug_path = new FlowEdge[this.intersection_count + 1];
}
public void addEdge(int node, FlowEdge edge) {
if (!this.graph.containsKey(node)) {
this.graph.put(node, new ArrayList<FlowEdge>());
}
this.graph.get(node).add(edge);
}
public int getMaxFlow() {
int max_flow = 0;
int src = 1;
int sink = this.intersection_count;
while (this.hasAugmentedPath(src, sink)) {
int flow_to_add = Integer.MAX_VALUE;
for (int n = sink; n != src; n = this.aug_path[n].other(n)) {
FlowEdge edge = this.aug_path[n];
flow_to_add = Math.min(flow_to_add, edge.getResidualCapacityTo(n));
}
for (int n = sink; n != src; n = this.aug_path[n].other(n)) {
FlowEdge edge = this.aug_path[n];
edge.addFlowTo(n, flow_to_add);
}
max_flow += flow_to_add;
}
return max_flow;
}
private boolean hasAugmentedPath(int n1, int n2) {
boolean[] visited = new boolean[this.intersection_count + 1];
Queue<Integer> queue = new LinkedList<Integer>();
queue.add(n1);
visited[n1] = true;
while (!queue.isEmpty()) {
int size = queue.size();
int i = 0;
while (i < size) {
int n = queue.poll();
// Be careful to deal with the corner case where there is no ditch
// between pond and stream (input: 0 2)
if (this.graph.containsKey(n)) {
for (FlowEdge edge : this.graph.get(n)) {
int other = edge.other(n);
if (edge.getResidualCapacityTo(other) != 0 && !visited[other]) {
this.aug_path[other] = edge;
visited[other] = true;
queue.add(other);
}
}
}
i++;
}
}
return visited[n2];
}
}
private static class FlowEdge {
private final int v, w;
private final int capacity;
private int flow;
public FlowEdge(int v, int w, int capacity) {
this.v = v;
this.w = w;
this.capacity = capacity;
}
public int other(int n) {
return n == this.v ? this.w : this.v;
}
public int getResidualCapacityTo(int n) {
return n == this.w ? (this.capacity - this.flow) : this.flow;
}
public void addFlowTo(int n, int value) {
int delta = (n == this.w) ? value : -value;
this.flow += delta;
}
}
public static void main(String[] args) throws IOException {
BufferedReader input = new BufferedReader(new FileReader("ditch.in"));
String[] N_M = input.readLine().split(" ");
int ditch_count = Integer.parseInt(N_M[0]);
int intersection_count = Integer.parseInt(N_M[1]);
FlowGraph graph = new FlowGraph(intersection_count);
for (int i = 0; i < ditch_count; i++) {
String[] src_dst_cap = input.readLine().split(" ");
int src = Integer.parseInt(src_dst_cap[0]);
int dst = Integer.parseInt(src_dst_cap[1]);
int cap = Integer.parseInt(src_dst_cap[2]);
FlowEdge edge = new FlowEdge(src, dst, cap);
graph.addEdge(src, edge);
graph.addEdge(dst, edge);
}
input.close();
int max_flow = graph.getMaxFlow();
PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter("ditch.out")));
// Be careful max_flow needs to be converted to string before writing to file !!!
// Otherwise, max_flow will be considered as the index of the character in ASCII.
output.write(max_flow + "\n");
output.close();
}
}