-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbutter.java
125 lines (113 loc) · 4.19 KB
/
butter.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
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.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;
/*
ID: Xu Yan
LANG: JAVA
TASK: butter
*/
/**
* Thoughts: I approached the problem with Floyd-Warshall algorithm firstly.
* The graph vertex is pasture in this problem (2 <= |V| <= 800).
* Since the time complexity of Floyd-Warshall algorithm is O(|V|^3), I got a TLE.
* After a second thought, this graph is pretty sparse, because
* the number of edges in graph is |C|, which is in [1,1450] (|E| << |V|^2).
* Therefore, a shortest path algorithm using |E| is desirable
* => Bellman-Ford/SPFA: O(|V| * |E|)
* => Dijkstra: O(|E| + |V|log|V|)
*
* Pitfalls:
*
* Take-away tips:
*
* @author Xu Yan
* @date July 11th, 2016
*/
public class butter {
private static class Pasture {
int id;
int distance_to_source;
Map<Integer,Integer> neighbors; // id <-> distance
public Pasture(int id) {
this.id = id;
this.distance_to_source = Integer.MAX_VALUE;
this.neighbors = new HashMap<Integer,Integer>();
}
}
public static void main(String[] args) throws IOException, Exception {
BufferedReader f = new BufferedReader(new FileReader("butter.in"));
StringTokenizer inputs = new StringTokenizer(f.readLine());
int N = Integer.parseInt(inputs.nextToken());
int P = Integer.parseInt(inputs.nextToken());
int C = Integer.parseInt(inputs.nextToken());
Pasture[] pastures = new Pasture[P+1];
for (int i = 1; i <= P; i++) {
pastures[i] = new Pasture(i);
}
int[] cow_in_pasture = new int[P+1]; // Record how many cows in each pasture
Set<Integer> p_c = new HashSet<Integer>();
for (int i = 0; i < N; i++) {
int pasture_id = Integer.parseInt(new StringTokenizer(f.readLine()).nextToken());
cow_in_pasture[pasture_id] ++;
p_c.add(pasture_id);
}
for (int path_index = 0; path_index < C; path_index++) {
StringTokenizer path_token = new StringTokenizer(f.readLine());
int source_pasture_index = Integer.parseInt(path_token.nextToken());
int destination_pasture_index = Integer.parseInt(path_token.nextToken());
int path_length = Integer.parseInt(path_token.nextToken());
pastures[source_pasture_index].neighbors.put(destination_pasture_index, path_length);
pastures[destination_pasture_index].neighbors.put(source_pasture_index, path_length);
}
f.close();
int min_distance = Integer.MAX_VALUE;
// Run SPFA Algorithm P times to find the SP between all pairs of pastures
for (int source_id = 1; source_id <= P; source_id++) {
Queue<Integer> queue = new LinkedList<Integer>();
boolean[] in_queue = new boolean[P+1];
pastures[source_id].distance_to_source = 0;
queue.add(source_id);
while (!queue.isEmpty()) {
int pasture_id = queue.poll();
in_queue[pasture_id] = false;
Pasture current_pasture = pastures[pasture_id];
for (int neighbor_id : current_pasture.neighbors.keySet()) {
int new_distance = current_pasture.distance_to_source + current_pasture.neighbors.get(neighbor_id);
if (new_distance < pastures[neighbor_id].distance_to_source) {
pastures[neighbor_id].distance_to_source = new_distance;
if (!in_queue[neighbor_id]) {
queue.add(neighbor_id);
in_queue[neighbor_id] = true;
}
}
}
}
// Be careful there may be multiple cows in a pasture
// Place butter in pasture 'source_id'
int distance_candidate = 0;
for (int p_id : p_c) {
distance_candidate += pastures[p_id].distance_to_source * cow_in_pasture[p_id];
}
min_distance = Math.min(min_distance, distance_candidate);
resetDistanceToSource(pastures);
}
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("butter.out")));
out.println(min_distance);
out.close();
}
private static void resetDistanceToSource(Pasture[] pastures) {
for (int i = 1; i < pastures.length; i++) {
pastures[i].distance_to_source = Integer.MAX_VALUE;
}
}
}