Add code
This commit is contained in:
parent
6fef06fdef
commit
fc5aee5646
83
Couple.java
Normal file
83
Couple.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container to ease passing around a tuple of two objects. This object provides a sensible
|
||||||
|
* implementation of equals(), returning true if equals() is true on each of the contained
|
||||||
|
* objects.
|
||||||
|
*
|
||||||
|
* @link https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/Pair.java
|
||||||
|
*/
|
||||||
|
public class Couple<F, S> {
|
||||||
|
public final F first;
|
||||||
|
public final S second;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for a Couple.
|
||||||
|
*
|
||||||
|
* @param first the first object in the Couple
|
||||||
|
* @param second the second object in the Couple
|
||||||
|
*/
|
||||||
|
public Couple(F first, S second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the two objects for equality by delegating to their respective
|
||||||
|
* {@link Object#equals(Object)} methods.
|
||||||
|
*
|
||||||
|
* @param o the {@link Couple} to which this one is to be checked for equality
|
||||||
|
* @return true if the underlying objects of the Couple are both considered
|
||||||
|
* equal
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof Couple)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Couple<?, ?> p = (Couple<?, ?>) o;
|
||||||
|
return Objects.equals(p.first, first) && Objects.equals(p.second, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a hash code using the hash codes of the underlying objects
|
||||||
|
*
|
||||||
|
* @return a hashcode of the Couple
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Couple{" + String.valueOf(first) + " " + String.valueOf(second) + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for creating an appropriately typed couple.
|
||||||
|
*
|
||||||
|
* @param a the first object in the Couple
|
||||||
|
* @param b the second object in the Couple
|
||||||
|
* @return a Couple that is templatized with the types of a and b
|
||||||
|
*/
|
||||||
|
public static <A, B> Couple<A, B> create(A a, B b) {
|
||||||
|
return new Couple<A, B>(a, b);
|
||||||
|
}
|
||||||
|
}
|
129
DFS.java
Normal file
129
DFS.java
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package CompetitiveProgramming.Uva;
|
||||||
|
|
||||||
|
import CompetitiveProgramming.DirectedMultiGraph;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class
|
||||||
|
M11709
|
||||||
|
{
|
||||||
|
static DirectedMultiGraph g, g_transpose;
|
||||||
|
static int n_nodes, // P
|
||||||
|
T,
|
||||||
|
idx;
|
||||||
|
static Map<String, Integer> name_idx;
|
||||||
|
private static int number_of_scc = 0,
|
||||||
|
current_scc_n_nodes = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WARNING: Changes all graph nodes' visited state to true
|
||||||
|
* temporary storage: current_scc_n_nodes won't be reset by the end
|
||||||
|
*
|
||||||
|
* Time complexity: O(E+N)
|
||||||
|
* void operations: Will set number_of_scc
|
||||||
|
*
|
||||||
|
* @param g DirectedMultiGraph The graph to be used
|
||||||
|
* @param u int The start point
|
||||||
|
* @param dfs_finished_stack Stack<int> ending_sequence I/O (optional) If DAG is given,
|
||||||
|
* it will correspond to a top sort (total order)
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
private static void
|
||||||
|
dfs_visit(DirectedMultiGraph g, int u, ArrayDeque<Integer>... dfs_finished_stack) {
|
||||||
|
g.seen[u] = true;
|
||||||
|
++current_scc_n_nodes;
|
||||||
|
|
||||||
|
for (int w : g.edges(u)) {
|
||||||
|
if (!g.seen[w]) {
|
||||||
|
dfs_visit(g, w, dfs_finished_stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a dfs_finished_stack was supplied to be filled
|
||||||
|
if (dfs_finished_stack.length == 1) {
|
||||||
|
dfs_finished_stack[0].addFirst(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time complexity: O(E+N)
|
||||||
|
private static void
|
||||||
|
kosaraju_sharir(DirectedMultiGraph g, DirectedMultiGraph g_transpose, int n_nodes) {
|
||||||
|
// DFS visit the graph
|
||||||
|
ArrayDeque<Integer> dfs_finished_stack = new ArrayDeque<>();
|
||||||
|
for (int v = 0; v < n_nodes; ++v) {
|
||||||
|
if (!g.seen[v]) {
|
||||||
|
dfs_visit(g, v, dfs_finished_stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset globals
|
||||||
|
current_scc_n_nodes = 0;
|
||||||
|
number_of_scc = 0;
|
||||||
|
|
||||||
|
// DFS visit in transposed graph using dfs_finished_stack seq
|
||||||
|
while (!dfs_finished_stack.isEmpty()) {
|
||||||
|
int v = dfs_finished_stack.removeFirst();
|
||||||
|
|
||||||
|
// New component is being discovered
|
||||||
|
if (!g_transpose.seen[v]) {
|
||||||
|
current_scc_n_nodes = 0;
|
||||||
|
dfs_visit(g_transpose, v);
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
++number_of_scc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int
|
||||||
|
idx_in_graph(String name) {
|
||||||
|
Integer u = name_idx.get(name);
|
||||||
|
if (u == null) {
|
||||||
|
u = idx++;
|
||||||
|
name_idx.put(name, u);
|
||||||
|
}
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean
|
||||||
|
generate_structures(Scanner stdin) {
|
||||||
|
if (n_nodes == 0 && T == 0) return false;
|
||||||
|
stdin.nextLine(); // flush from int buffer
|
||||||
|
name_idx = new HashMap<>(n_nodes);
|
||||||
|
idx = 0;
|
||||||
|
g = new DirectedMultiGraph(n_nodes, true);
|
||||||
|
g_transpose = new DirectedMultiGraph(n_nodes, true);
|
||||||
|
|
||||||
|
for (int p = 0; p < n_nodes; ++p) {
|
||||||
|
String name = stdin.nextLine();
|
||||||
|
idx_in_graph(name);
|
||||||
|
}
|
||||||
|
for (int t = 0; t < T; ++t) {
|
||||||
|
String u_name = stdin.nextLine(),
|
||||||
|
w_name = stdin.nextLine();
|
||||||
|
int u = idx_in_graph(u_name),
|
||||||
|
w = idx_in_graph(w_name);
|
||||||
|
g.link_first(u, w);
|
||||||
|
g_transpose.link_first(w, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void
|
||||||
|
main(String[] args) {
|
||||||
|
// Input and Data Representation
|
||||||
|
Scanner stdin = new Scanner(System.in);
|
||||||
|
while (true) {
|
||||||
|
n_nodes = stdin.nextInt();
|
||||||
|
T = stdin.nextInt();
|
||||||
|
if (!generate_structures(stdin)) break;
|
||||||
|
// Process
|
||||||
|
kosaraju_sharir(g, g_transpose, n_nodes);
|
||||||
|
// Output
|
||||||
|
System.out.println(number_of_scc);
|
||||||
|
}
|
||||||
|
// That's all folks
|
||||||
|
stdin.close();
|
||||||
|
}
|
||||||
|
}
|
85
DirectedMultiGraph.java
Normal file
85
DirectedMultiGraph.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DirectedMultiGraph class is a structure to store a non-weighted
|
||||||
|
* graph of nodes named 0 through N-1.
|
||||||
|
* The implementation uses an adjacency-lists representation.
|
||||||
|
* @author Diogo Peralta Cordeiro <diogo@fc.up.pt>
|
||||||
|
*/
|
||||||
|
public class
|
||||||
|
DirectedMultiGraph
|
||||||
|
{
|
||||||
|
private final List<LinkedList<Integer>> edges;
|
||||||
|
public final int[] out_degree, in_degree;
|
||||||
|
public int n_nodes, n_edges; // N, #Edges, respectively
|
||||||
|
|
||||||
|
// O(n) to construct the structure
|
||||||
|
public
|
||||||
|
DirectedMultiGraph (int n_nodes)
|
||||||
|
{
|
||||||
|
this.n_nodes = n_nodes;
|
||||||
|
this.n_edges = 0;
|
||||||
|
this.edges = new ArrayList<>(n_nodes);
|
||||||
|
this.out_degree = new int[n_nodes];
|
||||||
|
this.in_degree = new int[n_nodes];
|
||||||
|
for (int i = 0; i < n_nodes; ++i)
|
||||||
|
{
|
||||||
|
this.edges.add(i, new LinkedList<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to get the adjacency-list for a node
|
||||||
|
public LinkedList<Integer>
|
||||||
|
edges (int u)
|
||||||
|
{
|
||||||
|
return this.edges.get(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to get the first adjacency of a node
|
||||||
|
public int
|
||||||
|
first_edge (int u)
|
||||||
|
{
|
||||||
|
return this.edges.get(u).getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to add an adjacency
|
||||||
|
public final void
|
||||||
|
link_first (int u, int w)
|
||||||
|
{
|
||||||
|
// If we don't want a Multi-graph and can't avoid
|
||||||
|
// duplicate links from the outside, uncomment the following
|
||||||
|
// line
|
||||||
|
//if (node_links(u).contains(w)) return;
|
||||||
|
this.edges(u).addFirst(w);
|
||||||
|
++this.out_degree[u];
|
||||||
|
++this.in_degree[w];
|
||||||
|
++this.n_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to remove an adjacency
|
||||||
|
public void
|
||||||
|
unlink_first (int u)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int w = this.edges(u).removeFirst();
|
||||||
|
--this.out_degree[u];
|
||||||
|
--this.in_degree[w];
|
||||||
|
--this.n_edges;
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
// void.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience: In case the requester needs to hold such type of information about the nodes
|
||||||
|
public boolean[] seen;
|
||||||
|
public
|
||||||
|
DirectedMultiGraph (int n_nodes, boolean have_seen)
|
||||||
|
{
|
||||||
|
this(n_nodes);
|
||||||
|
if (have_seen)
|
||||||
|
seen = new boolean[n_nodes];
|
||||||
|
}
|
||||||
|
}
|
275
DirectedWeightedGraph.java
Normal file
275
DirectedWeightedGraph.java
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DirectedWeightedGraph class is a structure to store a n-weighted
|
||||||
|
* graph of nodes named 0 through N-1.
|
||||||
|
* The implementation uses an adjacency-lists representation for the graph
|
||||||
|
* and a HashMap indexed by strings of the form "u-v", u and v being nodes,
|
||||||
|
* the map's values are a List of generic type.
|
||||||
|
* Each edge can have a different number of weights (or even none).
|
||||||
|
* @author Diogo Peralta Cordeiro <diogo@fc.up.pt>
|
||||||
|
*/
|
||||||
|
public class
|
||||||
|
DirectedWeightedGraph<T>
|
||||||
|
{
|
||||||
|
private final List<LinkedList<Integer>> edges;
|
||||||
|
private final Map<String, List<T>> edges_weights;
|
||||||
|
public int n_nodes, n_edges; // N, #Edges, respectively
|
||||||
|
|
||||||
|
// O(n) to construct the structure
|
||||||
|
public
|
||||||
|
DirectedWeightedGraph (int n_nodes)
|
||||||
|
{
|
||||||
|
this.n_nodes = n_nodes;
|
||||||
|
this.n_edges = 0;
|
||||||
|
this.edges = new ArrayList<>(n_nodes);
|
||||||
|
this.edges_weights = new HashMap<>(n_nodes);
|
||||||
|
for (int i = 0; i < n_nodes; ++i)
|
||||||
|
{
|
||||||
|
this.edges.add(i, new LinkedList<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to get the adjacency-list for a node
|
||||||
|
public LinkedList<Integer>
|
||||||
|
edges (int u)
|
||||||
|
{
|
||||||
|
return this.edges.get(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to get the weights list
|
||||||
|
public List<T>
|
||||||
|
weight (int u, int w)
|
||||||
|
{
|
||||||
|
return this.edges_weights.get(u + "-" + w);
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to add a node to the last position of the adjacency-list
|
||||||
|
// O(1) to update the weight of an existing edge
|
||||||
|
@SafeVarargs
|
||||||
|
public final void
|
||||||
|
link (int u, int w, T... weight)
|
||||||
|
{
|
||||||
|
// O(1) to ensure we don't make a MultiGraph
|
||||||
|
if (!this.edges(u).contains(w)) {
|
||||||
|
// O(1) to add an adjacency
|
||||||
|
this.edges(u).addLast(w);
|
||||||
|
|
||||||
|
++this.n_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) to put or update a weight, if we want to
|
||||||
|
this.edges_weights.put(u + "-" + w, Arrays.asList(weight));
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(n) to remove a node
|
||||||
|
public void
|
||||||
|
delete_node (int u)
|
||||||
|
{
|
||||||
|
for (int w = 0; w < this.n_nodes; ++w)
|
||||||
|
{
|
||||||
|
this.unlink(u, w);
|
||||||
|
this.unlink(w, u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(n) to remove an adjacency
|
||||||
|
public void
|
||||||
|
unlink (int u, int w)
|
||||||
|
{
|
||||||
|
// O(n)
|
||||||
|
this.edges(u).remove((Integer) w);
|
||||||
|
|
||||||
|
// O(1)
|
||||||
|
this.edges_weights.remove(u + "-" + w);
|
||||||
|
|
||||||
|
--this.n_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UTILS */
|
||||||
|
|
||||||
|
// O(#Edges + N*lg(N))
|
||||||
|
public List<Object>
|
||||||
|
int_dijkstra(int s) {
|
||||||
|
/* Set Data Structures */
|
||||||
|
int[] dist = new int[this.n_nodes];
|
||||||
|
List<List<Integer>> come_from = new ArrayList<>(this.n_nodes);
|
||||||
|
for (int i = 0; i < this.n_nodes; ++i) {
|
||||||
|
dist[i] = 1000000000; // 1e9 to avoid overflow
|
||||||
|
come_from.add(i, new LinkedList<>());
|
||||||
|
}
|
||||||
|
// Compare by distance, then by index
|
||||||
|
TreeSet<Integer> to_explore = new TreeSet<>(Comparator.comparingInt((Integer i) -> dist[i]).thenComparingInt(i -> i));
|
||||||
|
|
||||||
|
// Let's find distances from s
|
||||||
|
dist[s] = 0;
|
||||||
|
to_explore.add(s);
|
||||||
|
|
||||||
|
// Dijkstra's Algorithm
|
||||||
|
while (!to_explore.isEmpty()) {
|
||||||
|
int u = to_explore.pollFirst();
|
||||||
|
// Assert: u.distance is the true shortest distance from s to u
|
||||||
|
// Assert: u is never put back into to_explore
|
||||||
|
this.edges(u).forEach((w) -> {
|
||||||
|
int edge_cost = (int) this.weight(u, w).get(0);
|
||||||
|
int dist_w = dist[u] + edge_cost;
|
||||||
|
if (dist_w < dist[w]) {
|
||||||
|
come_from.get(w).clear();
|
||||||
|
come_from.get(w).add(u);
|
||||||
|
// Decrease key with new distance
|
||||||
|
to_explore.remove(w);
|
||||||
|
dist[w] = dist_w;
|
||||||
|
to_explore.add(w);
|
||||||
|
} else if (dist_w == dist[w]) {
|
||||||
|
come_from.get(w).add(u);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// That's all folks.
|
||||||
|
return Arrays.asList(dist, come_from);
|
||||||
|
}
|
||||||
|
public List<Object>
|
||||||
|
double_dijkstra(int s) {
|
||||||
|
/* Set Data Structures */
|
||||||
|
double[] dist = new double[this.n_nodes];
|
||||||
|
List<List<Integer>> come_from = new ArrayList<>(this.n_nodes);
|
||||||
|
for (int i = 0; i < this.n_nodes; ++i) {
|
||||||
|
dist[i] = 1000000000; // 1e9 to avoid overflow
|
||||||
|
come_from.add(i, new LinkedList<>());
|
||||||
|
}
|
||||||
|
// Compare by distance, then by index
|
||||||
|
TreeSet<Integer> to_explore = new TreeSet<>(Comparator.comparingDouble((Integer i) -> dist[i]).thenComparingInt(i -> i));
|
||||||
|
|
||||||
|
// Let's find distances from s
|
||||||
|
dist[s] = 0;
|
||||||
|
to_explore.add(s);
|
||||||
|
|
||||||
|
// Dijkstra's Algorithm
|
||||||
|
while (!to_explore.isEmpty()) {
|
||||||
|
int u = to_explore.pollFirst();
|
||||||
|
// Assert: u.distance is the true shortest distance from s to u
|
||||||
|
// Assert: u is never put back into to_explore
|
||||||
|
this.edges(u).forEach((w) -> {
|
||||||
|
double edge_cost = (double) this.weight(u, w).get(0);
|
||||||
|
double dist_w = dist[u] + edge_cost;
|
||||||
|
if (Double.compare(dist_w, dist[w]) < 0) {
|
||||||
|
come_from.get(w).clear();
|
||||||
|
come_from.get(w).add(u);
|
||||||
|
// Decrease key with new distance
|
||||||
|
to_explore.remove(w);
|
||||||
|
dist[w] = dist_w;
|
||||||
|
to_explore.add(w);
|
||||||
|
} else if (Double.compare(dist_w, dist[w]) == 0) {
|
||||||
|
come_from.get(w).add(u);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// That's all folks.
|
||||||
|
return Arrays.asList(dist, come_from);
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(#Edges + N*lg(N))
|
||||||
|
public int[]
|
||||||
|
int_prim() {
|
||||||
|
/* Set Data Structures */
|
||||||
|
int[] dist = new int[this.n_nodes];
|
||||||
|
boolean[] in_tree = new boolean[this.n_nodes];
|
||||||
|
int[] come_from = new int[this.n_nodes];
|
||||||
|
Arrays.fill(dist, 1000000000); // 1e9 to avoid overflow
|
||||||
|
TreeSet<Integer> to_explore = new TreeSet<>(Comparator.comparingInt((Integer i) -> dist[i]).thenComparingInt(i -> i));
|
||||||
|
|
||||||
|
// Let's find distances from s
|
||||||
|
int s = 0;
|
||||||
|
dist[s] = 0;
|
||||||
|
to_explore.add(s);
|
||||||
|
|
||||||
|
while (!to_explore.isEmpty()) {
|
||||||
|
int u = to_explore.pollFirst();
|
||||||
|
in_tree[u] = true;
|
||||||
|
// Let t be the graph made of nodes with in_tree = true,
|
||||||
|
// and edges {(w - come_from[w]), for w in g.nodes excluding s}
|
||||||
|
// Assert: t is part of an MST for g
|
||||||
|
this.edges(u).forEach((w) -> {
|
||||||
|
int edge_cost = (int) this.weight(u, w).get(0);
|
||||||
|
if (!in_tree[w] && edge_cost < dist[w]) {
|
||||||
|
come_from[w] = u;
|
||||||
|
to_explore.remove(w);
|
||||||
|
dist[w] = edge_cost;
|
||||||
|
to_explore.add(w);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// That's all folks.
|
||||||
|
return come_from;
|
||||||
|
}
|
||||||
|
public int[]
|
||||||
|
double_prim() {
|
||||||
|
/* Set Data Structures */
|
||||||
|
double[] dist = new double[this.n_nodes];
|
||||||
|
boolean[] in_tree = new boolean[this.n_nodes];
|
||||||
|
int[] come_from = new int[this.n_nodes];
|
||||||
|
Arrays.fill(dist, 1000000000); // 1e9 to avoid overflow
|
||||||
|
TreeSet<Integer> to_explore = new TreeSet<>(Comparator.comparingDouble((Integer i) -> dist[i]).thenComparingInt(i -> i));
|
||||||
|
|
||||||
|
// Let's find distances from s
|
||||||
|
int s = 0;
|
||||||
|
dist[s] = 0;
|
||||||
|
to_explore.add(s);
|
||||||
|
|
||||||
|
while (!to_explore.isEmpty()) {
|
||||||
|
int u = to_explore.pollFirst();
|
||||||
|
in_tree[u] = true;
|
||||||
|
// Let t be the graph made of nodes with in_tree = true,
|
||||||
|
// and edges {(w - come_from[w]), for w in g.nodes excluding s}
|
||||||
|
// Assert: t is part of an MST for g
|
||||||
|
this.edges(u).forEach((w) -> {
|
||||||
|
double edge_cost = (double) this.weight(u, w).get(0);
|
||||||
|
if (!in_tree[w] && Double.compare(edge_cost, dist[w]) < 0) {
|
||||||
|
come_from[w] = u;
|
||||||
|
to_explore.remove(w);
|
||||||
|
dist[w] = edge_cost;
|
||||||
|
to_explore.add(w);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// That's all folks.
|
||||||
|
return come_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(N*#Edges)
|
||||||
|
public int[]
|
||||||
|
int_bellman_ford (int s) throws Exception {
|
||||||
|
int[] min_weight = new int[this.n_nodes];
|
||||||
|
// best estimate so far of minimum weight from s to another vertex
|
||||||
|
Arrays.fill(min_weight, 1000000000); // 1e9 to avoid overflow
|
||||||
|
min_weight[s] = 0;
|
||||||
|
|
||||||
|
// Repeat
|
||||||
|
for (int i = 0; i < this.n_nodes; ++i) {
|
||||||
|
// relax all the edges
|
||||||
|
for (int u = 0; u < this.n_nodes; ++u) {
|
||||||
|
for (int w : this.edges(u)) {
|
||||||
|
int edge_cost = (int) this.weight(u, w).get(0);
|
||||||
|
min_weight[w] = Math.min(min_weight[u] + edge_cost, min_weight[w]);
|
||||||
|
// Assert: v.min_weight >= true minimum weight from s to v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int u = 0; u < this.n_nodes; ++u) {
|
||||||
|
for (int w : this.edges(u)) {
|
||||||
|
int edge_cost = (int) this.weight(u, w).get(0);
|
||||||
|
if (min_weight[u] + edge_cost < min_weight[w]) {
|
||||||
|
throw new Exception("Negative-weight cycle detected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// That's all folks.
|
||||||
|
return min_weight;
|
||||||
|
}
|
||||||
|
}
|
10
FastPrint.java
Normal file
10
FastPrint.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package ProgrammingChallenges;
|
||||||
|
// FastPrint (remember to call FastPrint.out.close() at the end)
|
||||||
|
// Pedro Ribeiro (DCC/FCUP)
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
public class FastPrint {
|
||||||
|
public static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
|
||||||
|
}
|
61
FastScanner.java
Normal file
61
FastScanner.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package ProgrammingChallenges;
|
||||||
|
// FastScanner
|
||||||
|
// Pedro Ribeiro (DCC/FCUP)
|
||||||
|
// Minor edits by Diogo Cordeiro
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
public class FastScanner {
|
||||||
|
BufferedReader br;
|
||||||
|
StringTokenizer st;
|
||||||
|
|
||||||
|
public FastScanner(InputStream stream) {
|
||||||
|
br = new BufferedReader(new InputStreamReader(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String next() {
|
||||||
|
while (st == null || !st.hasMoreElements()) {
|
||||||
|
String ffs = null;
|
||||||
|
try {
|
||||||
|
ffs = br.readLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (ffs != null)
|
||||||
|
st = new StringTokenizer(ffs);
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
return st.nextToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
//public Integer nextInt() {
|
||||||
|
public int nextInt() {
|
||||||
|
//String n = next();
|
||||||
|
//if (n == null) return null;
|
||||||
|
//return Integer.parseInt(n);
|
||||||
|
return Integer.parseInt(next());
|
||||||
|
}
|
||||||
|
|
||||||
|
public long nextLong() {
|
||||||
|
return Long.parseLong(next());
|
||||||
|
}
|
||||||
|
|
||||||
|
public double nextDouble() {
|
||||||
|
return Double.parseDouble(next());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String nextLine() {
|
||||||
|
String str = "";
|
||||||
|
try {
|
||||||
|
str = br.readLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
90
FloydWarshall.java
Normal file
90
FloydWarshall.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/* Input */
|
||||||
|
// Information about the group
|
||||||
|
int n_elements = stdin.nextInt(),
|
||||||
|
start = stdin.nextInt(),
|
||||||
|
budget = stdin.nextInt(),
|
||||||
|
// Information about the network
|
||||||
|
n_nodes = stdin.nextInt(),
|
||||||
|
n_edges = stdin.nextInt(),
|
||||||
|
NO_EDGE = 1000000000; // 1e9 to avoid overflow
|
||||||
|
// Graph as a adjacency-matrix
|
||||||
|
int[][] adj = new int[n_nodes][n_nodes];
|
||||||
|
for (int i = 0; i < n_nodes; ++i)
|
||||||
|
{
|
||||||
|
Arrays.fill(adj[i], NO_EDGE);
|
||||||
|
adj[i][i] = 0;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < n_edges; ++i)
|
||||||
|
{
|
||||||
|
int source = stdin.nextInt()-1,
|
||||||
|
dest = stdin.nextInt()-1,
|
||||||
|
spots = stdin.nextInt(),
|
||||||
|
cost = stdin.nextInt();
|
||||||
|
|
||||||
|
if (spots >= n_elements
|
||||||
|
&& cost <= budget) // prevents stupidly expensive edges
|
||||||
|
{
|
||||||
|
adj[source][dest] = cost;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
adj[source][dest] = NO_EDGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's keep a fast access to the path
|
||||||
|
int[][] path = new int[n_nodes][n_nodes];
|
||||||
|
for (int i = 0; i < n_nodes; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < n_nodes; ++j)
|
||||||
|
{
|
||||||
|
if (adj[i][j] == NO_EDGE)
|
||||||
|
{
|
||||||
|
path[i][j] = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path[i][j] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Floyd-Warshall */
|
||||||
|
for (int k = 0; k < n_nodes; ++k)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < n_nodes; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < n_nodes; ++j)
|
||||||
|
{
|
||||||
|
if (adj[i][j] > adj[i][k] + adj[k][j])
|
||||||
|
{
|
||||||
|
adj[i][j] = adj[i][k] + adj[k][j];
|
||||||
|
path[i][j] = path[k][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path from a given `start` to every other node in the graph
|
||||||
|
ArrayDeque<Integer> indexes = new ArrayDeque<>();
|
||||||
|
next_route:
|
||||||
|
for (int end = 0; end < n_nodes; ++end)
|
||||||
|
{
|
||||||
|
indexes.clear();
|
||||||
|
indexes.addFirst(end);
|
||||||
|
|
||||||
|
int current_end = end,
|
||||||
|
previous;
|
||||||
|
while (path[start][current_end] != start)
|
||||||
|
{
|
||||||
|
previous = path[start][current_end];
|
||||||
|
if (previous == -1) // No possible path
|
||||||
|
{
|
||||||
|
continue next_route;
|
||||||
|
}
|
||||||
|
indexes.addFirst(previous);
|
||||||
|
current_end = previous;
|
||||||
|
}
|
||||||
|
indexes.addFirst(start);
|
||||||
|
System.out.println("Get to node " + end + " costs " + adj[start][end] + ".");
|
||||||
|
}
|
26
InsertSort.java
Normal file
26
InsertSort.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class insertsort
|
||||||
|
{
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
int[] in = {5,1,2,3};
|
||||||
|
|
||||||
|
System.out.println("Before insertion sort: " + Arrays.toString(in));
|
||||||
|
|
||||||
|
for (int i = 1; i < in.length; ++i)
|
||||||
|
{
|
||||||
|
int j = i - 1; // Ensure we don't get in a off by one error
|
||||||
|
while (j >= 0 && in[j] > in[j + 1])
|
||||||
|
{
|
||||||
|
int t = in[j];
|
||||||
|
in[j] = in[j+1];
|
||||||
|
in[j+1] = t;
|
||||||
|
--j; // Ensure that all the positions before are still correct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("After insertion sort: " + Arrays.toString(in));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
34
Johnson.java
Normal file
34
Johnson.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// You have a graph G (original graph), with edge weight values v(u->w)
|
||||||
|
// You must call this function with a helper graph with a special node
|
||||||
|
// indexed 0 and zero-weight edges 0->w for all vertices w
|
||||||
|
// Time complexity: O(N^2 * lg N + N*#Edges)
|
||||||
|
// Returns APSP indexed as expected in the original graph (i.e.,
|
||||||
|
// shifting everything -1 to exclude the special node of the helper graph)
|
||||||
|
private static int[][]
|
||||||
|
int_johnson (DirectedWeightedGraph<Integer> hg) throws Exception
|
||||||
|
{
|
||||||
|
// Finish the helper graph by running Bellman-Ford on it
|
||||||
|
int[] h = hg.int_bellman_ford(0);
|
||||||
|
|
||||||
|
// Generate the tweaked graph
|
||||||
|
for (int u = 1; u < hg.n_nodes; ++u) {
|
||||||
|
hg.edges(u).forEach((w) -> {
|
||||||
|
int edge_cost = (int) hg.weight(u, w).get(0);
|
||||||
|
// Update edge's cost
|
||||||
|
hg.link(u, w, edge_cost + h[u] - h[w]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int [][] D = new int[hg.n_nodes-1][hg.n_nodes-1];
|
||||||
|
|
||||||
|
// Dijkstra on the tweaked graph
|
||||||
|
for (int u = 0; u < g.n_nodes-1; ++u) {
|
||||||
|
for (int w = 0; w < g.n_nodes-1; ++w) {
|
||||||
|
int[] delta = hg.int_dijkstra(u+1);
|
||||||
|
D[u][w] = delta[w+1] + h[w+1] - h[u+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Johnson drops mic.
|
||||||
|
return D;
|
||||||
|
}
|
91
LIS.java
Normal file
91
LIS.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package ProgrammingChallenges.Uva;
|
||||||
|
|
||||||
|
import ProgrammingChallenges.FastPrint;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class
|
||||||
|
UVA10534 {
|
||||||
|
// https://stackoverflow.com/a/17660641
|
||||||
|
// Time complexity: O(n*lg(n))
|
||||||
|
public static int[]
|
||||||
|
LIS(int[] a) {
|
||||||
|
int n = a.length;
|
||||||
|
int INF = 1000000000;
|
||||||
|
int[] seq = new int[n];
|
||||||
|
int[] d = new int[n + 1];
|
||||||
|
d[0] = -INF;
|
||||||
|
for (int i = 1; i < n + 1; ++i) {
|
||||||
|
seq[i - 1] = 1;
|
||||||
|
d[i] = INF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < n + 1; ++i) {
|
||||||
|
int low = 0,
|
||||||
|
high = i;
|
||||||
|
while (low <= high) {
|
||||||
|
int mid = low + (high - low) / 2;
|
||||||
|
if (d[mid] < a[i - 1]) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d[low] = a[i - 1];
|
||||||
|
seq[i - 1] = low;
|
||||||
|
}
|
||||||
|
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[]
|
||||||
|
reverse_arr(int[] seq) {
|
||||||
|
/*int[] reverse_seq = new int[seq.length];
|
||||||
|
for (int i = 0, j = seq.length-1; i < seq.length; ++i, --j)
|
||||||
|
reverse_seq[j] = seq[i];*/
|
||||||
|
return IntStream.range(0, seq.length)
|
||||||
|
.map(i -> seq[seq.length - 1 - i])
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[]
|
||||||
|
LDS(int[] seq) {
|
||||||
|
/*int[] reverse_seq = IntStream.range(0, seq.length)
|
||||||
|
.map(i -> seq[seq.length - 1 - i])
|
||||||
|
.toArray();*/
|
||||||
|
/*int[] reverse_seq = new int[seq.length];
|
||||||
|
for (int i = 0, j = seq.length-1; i < seq.length; ++i, --j)
|
||||||
|
reverse_seq[j] = seq[i];*/
|
||||||
|
return reverse_arr(LIS(reverse_arr(seq)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void
|
||||||
|
main(String[] args) {
|
||||||
|
Scanner stdin = new Scanner(System.in);
|
||||||
|
while (stdin.hasNext()) {
|
||||||
|
// Input
|
||||||
|
int N = stdin.nextInt();
|
||||||
|
int[] seq = new int[N];
|
||||||
|
for (int i = 0; i < N; ++i) {
|
||||||
|
seq[i] = stdin.nextInt();
|
||||||
|
}
|
||||||
|
//System.out.println(Arrays.toString(seq));
|
||||||
|
|
||||||
|
// Process
|
||||||
|
int[] lis = LIS(seq);
|
||||||
|
int[] lds = LDS(seq);
|
||||||
|
int ans = 0;
|
||||||
|
for (int i = 0; i < N; ++i) {
|
||||||
|
//System.out.println(lis[i] + " " + lds[i]);
|
||||||
|
int min = Math.min(lis[i], lds[i]);
|
||||||
|
ans = Math.max(ans, 2 * min - 1);
|
||||||
|
}
|
||||||
|
// Output
|
||||||
|
FastPrint.out.println(ans);
|
||||||
|
}
|
||||||
|
FastPrint.out.close();
|
||||||
|
}
|
||||||
|
}
|
32
README.md
32
README.md
@ -1,3 +1,33 @@
|
|||||||
# JavaAlgorithms
|
# JavaAlgorithms
|
||||||
These are some Java code I wrote throughout my first degree in CompSci.
|
These are some Java code I wrote throughout my first degree in Computer Science.
|
||||||
There is some third party code properly credited and with its associated license.
|
There is some third party code properly credited and with its associated license.
|
||||||
|
|
||||||
|
## Files Descriptions
|
||||||
|
|
||||||
|
### Code I wrote
|
||||||
|
* [Directed MultiGraph](DirectedMultiGraph.java) - Adjacency-list non-weighted directed multi-graphs (data structure)
|
||||||
|
* [Directed Weighted Graph](DirectedWeightedGraph.java) - Adjacency-list n-weighted directed graphs (data structure)
|
||||||
|
* [Dijkstra](DirectedWeightedGraph.java#L91) - Adjacency-list Dijkstra's algorithm implementation (SSC non-negative weights only)
|
||||||
|
* [Prim](DirectedWeightedGraph.java#L173) - Adjacency-list Prim's algorithm implementation (MST)
|
||||||
|
* [Bellman-Ford](DirectedWeightedGraph.java#L243) - Adjacency-list Bellman-ford (SSC)
|
||||||
|
* [Floyd Warshall](FloydWarshall.java) - Adjacency-matrix Floyd Warshall (APSP)
|
||||||
|
* [Johnson](Johnson.java) - Johnson's Algorithm (sparse graph APSP)
|
||||||
|
* [Insert Sort](InsertSort.java) - An Insertion Sort implementation (sorting)
|
||||||
|
* [DFS and Topological Sorting](DFS.java#L18) - Adjacency-list DFS with TopSort implementation (graph traversal and sorting)
|
||||||
|
* [Kosaraju-Sharir](DFS.java#L48) - Adjacency-list Kosaraju-Sharir implementation (SCC)
|
||||||
|
* [BFS non-directed SCC](bfs_scc.java) - Adjacency-list BFS implementation to identify SCC in a non-directed graph (graph traversal and SCC non-directed only)
|
||||||
|
* [BFS non-weighted SSC](bfs_shortest_path.java) - Adjacency-list BFS for shortest path in a non-weighted graph (SSC non-weighted)
|
||||||
|
* [LIS](LIS.java) - A Longest Increasing Sequence algorithm implmentation (substring)
|
||||||
|
* [Collections Count If](collections_count_if.java#L46) - Counts elements for which predicate p returns true (collection utility)
|
||||||
|
|
||||||
|
|
||||||
|
### Third party code
|
||||||
|
* [Couple](Couple.java) - A AOSP class to handle 2-tuples
|
||||||
|
* [Segment Tree](SegmentTree.java) - A Segment Tree data structure implementation derived from Segewick and Wayne's Algorithms, 4th ed. book
|
||||||
|
* [ValueThenKeyComparator](ValueThenKeyComparator.java) - A Comparator that sorts Map.Entry objects with Comparable keys and values, first by value, then by key
|
||||||
|
* [FastScanner](FastScanner.java) - Fast Input from STDIN in Java
|
||||||
|
* [FastPrint](FastPrint.java) - Fast Output from STDOUT in Java
|
||||||
|
|
||||||
|
### Example code
|
||||||
|
* [Activity Minimum Gap Schedulling](minimum_gap_schedulling.java) - Activity Minimum Gap Schedulling implementation (sorting)
|
||||||
|
* [Knapsack](knapsack.java) - Knapsack approximation solution using conditional binary search (search and optimization)
|
||||||
|
318
SegmentTree.java
Normal file
318
SegmentTree.java
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* A segment tree data structure.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code SegmentTree} class is a structure for efficient search of cumulative data.
|
||||||
|
* It performs Range Min, Max, Sum and Multiplication Queries in O(log(n)) time.
|
||||||
|
* <p>
|
||||||
|
* Also it has been develop with {@code LazyPropagation} for range updates, which means
|
||||||
|
* when you perform update operations over a range, the update process affects the least nodes as possible
|
||||||
|
* so that the bigger the range you want to update the less time it consumes to update it. Eventually those changes will be propagated
|
||||||
|
* to the children and the whole array will be up to date.
|
||||||
|
* <p>
|
||||||
|
* Example:
|
||||||
|
* <p>
|
||||||
|
* SegmentTreeHeap st = new SegmentTreeHeap(new Integer[]{1,3,4,2,1, -2, 4});
|
||||||
|
* st.update(0,3, 1)
|
||||||
|
* In the above case only the node that represents the range [0,3] will be updated (and not their children) so in this case
|
||||||
|
* the update task will be less than n*log(n)
|
||||||
|
* <p>
|
||||||
|
* Memory usage: O(n)
|
||||||
|
*
|
||||||
|
* @author Ricardo Pacheco (base code)
|
||||||
|
* @author Diogo Cordeiro (implemented range max and multiplication queries, plus other minor changes)
|
||||||
|
* @link https://algs4.cs.princeton.edu/99misc/SegmentTree.java.html
|
||||||
|
*/
|
||||||
|
public class SegmentTree {
|
||||||
|
|
||||||
|
private final STNode[] heap;
|
||||||
|
private final int[] array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time-Complexity: O(n*log(n))
|
||||||
|
*
|
||||||
|
* @param array the Initialization array
|
||||||
|
*/
|
||||||
|
public SegmentTree(int[] array) {
|
||||||
|
this.array = Arrays.copyOf(array, array.length);
|
||||||
|
// The max size of this array is about 2 * 2 ^ log2(n) + 1
|
||||||
|
int size = (int) (2 * Math.pow(2.0, Math.floor((Math.log(array.length) / Math.log(2.0)) + 1)));
|
||||||
|
heap = new STNode[size];
|
||||||
|
build(1, 0, array.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return array.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the Nodes of the Segment tree
|
||||||
|
private void build(int v, int from, int size) {
|
||||||
|
heap[v] = new STNode();
|
||||||
|
heap[v].from = from;
|
||||||
|
heap[v].to = from + size - 1;
|
||||||
|
|
||||||
|
if (size == 1) {
|
||||||
|
heap[v].sum = array[from];
|
||||||
|
heap[v].mul = array[from];
|
||||||
|
heap[v].min = array[from];
|
||||||
|
heap[v].max = array[from];
|
||||||
|
} else {
|
||||||
|
// Build childs
|
||||||
|
build(2 * v, from, size / 2);
|
||||||
|
build(2 * v + 1, from + size / 2, size - size / 2);
|
||||||
|
|
||||||
|
heap[v].sum = heap[2 * v].sum + heap[2 * v + 1].sum;
|
||||||
|
heap[v].mul = heap[2 * v].mul * heap[2 * v + 1].mul;
|
||||||
|
// min = min of the children
|
||||||
|
heap[v].min = Math.min(heap[2 * v].min, heap[2 * v + 1].min);
|
||||||
|
// max = max of the children
|
||||||
|
heap[v].max = Math.max(heap[2 * v].max, heap[2 * v + 1].max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range Sum Query
|
||||||
|
* <p>
|
||||||
|
* Time-Complexity: O(log(n))
|
||||||
|
*
|
||||||
|
* @param from from index
|
||||||
|
* @param to to index
|
||||||
|
* @return sum
|
||||||
|
*/
|
||||||
|
public int rsq(int from, int to) {
|
||||||
|
return rsq(1, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rsq(int v, int from, int to) {
|
||||||
|
STNode n = heap[v];
|
||||||
|
|
||||||
|
// If you did a range update that contained this node, you can infer the Sum without going down the tree
|
||||||
|
if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
|
||||||
|
return (to - from + 1) * n.pendingVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contains(from, to, n.from, n.to)) {
|
||||||
|
return heap[v].sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intersects(from, to, n.from, n.to)) {
|
||||||
|
propagate(v);
|
||||||
|
int leftSum = rsq(2 * v, from, to);
|
||||||
|
int rightSum = rsq(2 * v + 1, from, to);
|
||||||
|
|
||||||
|
return leftSum + rightSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range Multiplication Query
|
||||||
|
* <p>
|
||||||
|
* Time-Complexity: O(log(n))
|
||||||
|
*
|
||||||
|
* @param from from index
|
||||||
|
* @param to to index
|
||||||
|
* @author Diogo Peralta Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @return multiplication
|
||||||
|
*/
|
||||||
|
public int rmq(int from, int to) {
|
||||||
|
return rmq(1, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rmq(int v, int from, int to) {
|
||||||
|
STNode n = heap[v];
|
||||||
|
|
||||||
|
// If you did a range update that contained this node, you can infer the Product without going down the tree
|
||||||
|
if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
|
||||||
|
return (to - from + 1) * n.pendingVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contains(from, to, n.from, n.to)) {
|
||||||
|
return heap[v].mul;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intersects(from, to, n.from, n.to)) {
|
||||||
|
propagate(v);
|
||||||
|
int leftMul = rmq(2 * v, from, to);
|
||||||
|
int rightMul = rmq(2 * v + 1, from, to);
|
||||||
|
|
||||||
|
return leftMul * rightMul;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // neutral element
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range Min Query
|
||||||
|
* <p>
|
||||||
|
* Time-Complexity: O(log(n))
|
||||||
|
*
|
||||||
|
* @param from from index
|
||||||
|
* @param to to index
|
||||||
|
* @return min
|
||||||
|
*/
|
||||||
|
public int rMinQ(int from, int to) {
|
||||||
|
return rMinQ(1, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rMinQ(int v, int from, int to) {
|
||||||
|
STNode n = heap[v];
|
||||||
|
|
||||||
|
|
||||||
|
// If you did a range update that contained this node, you can infer the Min value without going down the tree
|
||||||
|
if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
|
||||||
|
return n.pendingVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contains(from, to, n.from, n.to)) {
|
||||||
|
return heap[v].min;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intersects(from, to, n.from, n.to)) {
|
||||||
|
propagate(v);
|
||||||
|
int leftMin = rMinQ(2 * v, from, to);
|
||||||
|
int rightMin = rMinQ(2 * v + 1, from, to);
|
||||||
|
|
||||||
|
return Math.min(leftMin, rightMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1000000000; // 1e9 to avoid overflow
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range Max Query
|
||||||
|
* <p>
|
||||||
|
* Time-Complexity: O(log(n))
|
||||||
|
*
|
||||||
|
* @param from from index
|
||||||
|
* @param to to index
|
||||||
|
* @author Diogo Peralta Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @return max
|
||||||
|
*/
|
||||||
|
public int rMaxQ(int from, int to) {
|
||||||
|
return rMaxQ(1, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rMaxQ(int v, int from, int to) {
|
||||||
|
STNode n = heap[v];
|
||||||
|
|
||||||
|
// If you did a range update that contained this node, you can infer the Max value without going down the tree
|
||||||
|
if (n.pendingVal != null && contains(n.from, n.to, from, to))
|
||||||
|
return n.pendingVal;
|
||||||
|
if (contains(from, to, n.from, n.to))
|
||||||
|
return heap[v].max;
|
||||||
|
if (intersects(from, to, n.from, n.to)) {
|
||||||
|
propagate(v);
|
||||||
|
int leftMax = rMaxQ(2 * v, from, to);
|
||||||
|
int rightMax = rMaxQ(2 * v + 1, from, to);
|
||||||
|
return Math.max(leftMax, rightMax);
|
||||||
|
}
|
||||||
|
return -1000000000; // 1e9 to avoid overflow
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range Update Operation.
|
||||||
|
* With this operation you can update either one position or a range of positions with a given number.
|
||||||
|
* The update operations will update the less it can to update the whole range (Lazy Propagation).
|
||||||
|
* The values will be propagated lazily from top to bottom of the segment tree.
|
||||||
|
* This behavior is really useful for updates on portions of the array
|
||||||
|
* <p>
|
||||||
|
* Time-Complexity: O(log(n))
|
||||||
|
*
|
||||||
|
* @param from from index
|
||||||
|
* @param to to index
|
||||||
|
* @param value value
|
||||||
|
*/
|
||||||
|
public void update(int from, int to, int value) {
|
||||||
|
update(1, from, to, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update(int v, int from, int to, int value) {
|
||||||
|
|
||||||
|
// The Node of the heap tree represents a range of the array with bounds: [n.from, n.to]
|
||||||
|
STNode n = heap[v];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the updating-range contains the portion of the current Node We lazily update it.
|
||||||
|
* This means We do NOT update each position of the vector, but update only some temporal
|
||||||
|
* values into the Node; such values into the Node will be propagated down to its children only when they need to.
|
||||||
|
*/
|
||||||
|
if (contains(from, to, n.from, n.to)) {
|
||||||
|
change(n, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.size() == 1) return;
|
||||||
|
|
||||||
|
if (intersects(from, to, n.from, n.to)) {
|
||||||
|
/**
|
||||||
|
* Before keeping going down to the tree We need to propagate the
|
||||||
|
* the values that have been temporally/lazily saved into this Node to its children
|
||||||
|
* So that when We visit them the values are properly updated
|
||||||
|
*/
|
||||||
|
propagate(v);
|
||||||
|
|
||||||
|
update(2 * v, from, to, value);
|
||||||
|
update(2 * v + 1, from, to, value);
|
||||||
|
|
||||||
|
n.sum = heap[2 * v].sum + heap[2 * v + 1].sum;
|
||||||
|
n.mul = heap[2 * v].mul * heap[2 * v + 1].mul;
|
||||||
|
n.min = Math.min(heap[2 * v].min, heap[2 * v + 1].min);
|
||||||
|
n.max = Math.max(heap[2 * v].max, heap[2 * v + 1].max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Propagate temporal values to children
|
||||||
|
private void propagate(int v) {
|
||||||
|
STNode n = heap[v];
|
||||||
|
|
||||||
|
if (n.pendingVal != null) {
|
||||||
|
change(heap[2 * v], n.pendingVal);
|
||||||
|
change(heap[2 * v + 1], n.pendingVal);
|
||||||
|
n.pendingVal = null; //unset the pending propagation value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the temporal values that will be propagated lazily
|
||||||
|
private void change(STNode n, int value) {
|
||||||
|
n.pendingVal = value;
|
||||||
|
n.sum = n.size() * value;
|
||||||
|
n.mul = n.size() * value;
|
||||||
|
n.min = value;
|
||||||
|
n.max = value;
|
||||||
|
array[n.from] = value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if the range1 contains range2
|
||||||
|
private boolean contains(int from1, int to1, int from2, int to2) {
|
||||||
|
return from2 >= from1 && to2 <= to1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check inclusive intersection, test if range1[from1, to1] intersects range2[from2, to2]
|
||||||
|
private boolean intersects(int from1, int to1, int from2, int to2) {
|
||||||
|
return from1 <= from2 && to1 >= from2 // (.[..)..] or (.[...]..)
|
||||||
|
|| from1 >= from2 && from1 <= to2; // [.(..]..) or [..(..)..
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Node class represents a partition range of the array.
|
||||||
|
static class STNode {
|
||||||
|
int sum, mul;
|
||||||
|
int min, max;
|
||||||
|
// Here we store the value that will be propagated lazily
|
||||||
|
Integer pendingVal = null;
|
||||||
|
int from;
|
||||||
|
int to;
|
||||||
|
|
||||||
|
int size() {
|
||||||
|
return to - from + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
17
ValueThenKeyComparator.java
Normal file
17
ValueThenKeyComparator.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// from: https://stackoverflow.com/a/3074324
|
||||||
|
public class ValueThenKeyComparator<K extends Comparable<? super K>,
|
||||||
|
V extends Comparable<? super V>>
|
||||||
|
implements Comparator<Map.Entry<K, V>> {
|
||||||
|
|
||||||
|
public int compare(Map.Entry<K, V> a, Map.Entry<K, V> b) {
|
||||||
|
int cmp1 = b.getValue().compareTo(a.getValue());
|
||||||
|
if (cmp1 != 0) {
|
||||||
|
return cmp1;
|
||||||
|
} else {
|
||||||
|
return a.getKey().compareTo(b.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
bfs_scc.java
Normal file
22
bfs_scc.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Pre-Process answers with a BFS (only possible if the graph is undirected)
|
||||||
|
int[] answers = new int[n];
|
||||||
|
ArrayDeque<Integer> queue = new ArrayDeque<>(n); // Queue
|
||||||
|
for (int s = n-1; s >= 0; --s)
|
||||||
|
{
|
||||||
|
if (answers[s] < s)
|
||||||
|
answers[s] = s;
|
||||||
|
queue.addFirst(s);
|
||||||
|
g.seen[s] = true;
|
||||||
|
while(!queue.isEmpty())
|
||||||
|
{
|
||||||
|
int u = queue.removeLast();
|
||||||
|
this.edges(u).forEach((w) -> {
|
||||||
|
if (!g.verts[w].seen)
|
||||||
|
{
|
||||||
|
queue.addFirst(w);
|
||||||
|
g.seen[w] = true;
|
||||||
|
answers[w] = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
bfs_shortest_path.java
Normal file
54
bfs_shortest_path.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
public class bfs_shortest_path
|
||||||
|
{
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
int n_nodes = 42;
|
||||||
|
boolean[] come_from = new boolean[n_nodes];
|
||||||
|
DirectedMultiGraph graph = new DirectedMultiGraph(n_nodes, true);
|
||||||
|
|
||||||
|
// Input
|
||||||
|
Scanner stdin = new Scanner(System.in);
|
||||||
|
int a = stdin.nextInt(), b, graph_root = a;
|
||||||
|
while ((b = stdin.nextInt()) != 0)
|
||||||
|
{
|
||||||
|
graph.link_first(a, b);
|
||||||
|
|
||||||
|
a = b;
|
||||||
|
}
|
||||||
|
int destination = a;
|
||||||
|
|
||||||
|
// BFS
|
||||||
|
ArrayDeque<Integer> to_explore = new ArrayDeque<>(); // Queue
|
||||||
|
to_explore.addFirst(graph_root);
|
||||||
|
graph.seen[graph_root] = true;
|
||||||
|
while (!to_explore.isEmpty())
|
||||||
|
{
|
||||||
|
int u = to_explore.removeLast();
|
||||||
|
this.edges(u).forEach((w) ->
|
||||||
|
{
|
||||||
|
if (!g.seen[w])
|
||||||
|
{
|
||||||
|
to_explore.addFirst(w);
|
||||||
|
g.seen[w] = true;
|
||||||
|
come_from[w] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output
|
||||||
|
ArrayDeque<Integer> path = new ArrayDeque<>();
|
||||||
|
path.addFirst(destination);
|
||||||
|
while(path.getFirst() != graph_root)
|
||||||
|
{
|
||||||
|
path.addFirst(graph.verts[path.getFirst()].come_from);
|
||||||
|
}
|
||||||
|
System.out.println("Output:");
|
||||||
|
for (int i : path)
|
||||||
|
{
|
||||||
|
System.out.println(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No leaks
|
||||||
|
stdin.close();
|
||||||
|
}
|
||||||
|
}
|
56
collections_count_if.java
Normal file
56
collections_count_if.java
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package ProgrammingChallenges.Uva;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.IntPredicate;
|
||||||
|
|
||||||
|
class UVA11286 {
|
||||||
|
static final int modules_per_term = 5;
|
||||||
|
|
||||||
|
public static void
|
||||||
|
main(String[] args) {
|
||||||
|
Scanner stdin = new Scanner(System.in);
|
||||||
|
|
||||||
|
// <Combination, Frequency>
|
||||||
|
Map<List<Integer>, Integer> freshers_modules = new HashMap<>();
|
||||||
|
|
||||||
|
while (stdin.hasNext()) {
|
||||||
|
int number_of_freshers = stdin.nextInt();
|
||||||
|
if (number_of_freshers == 0) {
|
||||||
|
break; // This was the last test case
|
||||||
|
}
|
||||||
|
freshers_modules.clear(); // Reset our data structure
|
||||||
|
|
||||||
|
for (int i = 0; i < number_of_freshers; ++i) {
|
||||||
|
List<Integer> modules = new ArrayList<>();
|
||||||
|
for (int j = 0; j < modules_per_term; ++j) {
|
||||||
|
int x = stdin.nextInt();
|
||||||
|
modules.add(x);
|
||||||
|
}
|
||||||
|
Collections.sort(modules);
|
||||||
|
freshers_modules.merge(modules, 1, Integer::sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Most popular pair
|
||||||
|
Map.Entry<List<Integer>, Integer> most_popular_module = Collections.max(freshers_modules.entrySet(), Map.Entry.comparingByValue());
|
||||||
|
// How many are as popular?
|
||||||
|
int max_students = most_popular_module.getValue();
|
||||||
|
int number_of_equally_popular_modules = collections_count_if(freshers_modules.values(), (a) -> a == max_students);
|
||||||
|
// This is the sh1ttiest prompt ever...
|
||||||
|
//System.out.println("max_students = "+max_students+"\nnumber_of_equally_popular_modules = "+number_of_equally_popular_modules+"\nnumber_of_freshers = "+number_of_freshers);
|
||||||
|
System.out.println(max_students * number_of_equally_popular_modules);
|
||||||
|
}
|
||||||
|
stdin.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int
|
||||||
|
collections_count_if(Collection<Integer> coll, IntPredicate op) {
|
||||||
|
int count = 0;
|
||||||
|
for (Integer v : coll) {
|
||||||
|
if (op.test((v))) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
knapsack.java
Normal file
65
knapsack.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class DAA011 {
|
||||||
|
public static void
|
||||||
|
main(String[] args)
|
||||||
|
{
|
||||||
|
FastScanner stdin = new FastScanner(System.in);
|
||||||
|
int n = stdin.nextInt();
|
||||||
|
int[] dist = new int[n];
|
||||||
|
int max = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
dist[i] = stdin.nextInt();
|
||||||
|
max += dist[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int p = stdin.nextInt(); p > 0; --p) {
|
||||||
|
FastPrint.out.println(cond_bsearch(dist, 0, max, stdin.nextInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
FastPrint.out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int
|
||||||
|
cond_bsearch(int[] haystack, int l, int r, int k)
|
||||||
|
{
|
||||||
|
//System.out.println(Arrays.toString(haystack));
|
||||||
|
//System.out.println("l: "+l+" | r: "+r+" | k: "+k);
|
||||||
|
while (l < r) {
|
||||||
|
int mid = l + (r - l) / 2;
|
||||||
|
|
||||||
|
if (cond(haystack, mid, k)) {
|
||||||
|
r = mid;
|
||||||
|
} else {
|
||||||
|
l = mid + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.out.println("l: "+l+" | r: "+r+" | k: "+k);
|
||||||
|
//return cond(haystack, l, k) ? l : -1;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean
|
||||||
|
cond(int[] dist, int needle, int k)
|
||||||
|
{
|
||||||
|
//System.out.println("needle: "+needle);
|
||||||
|
int acc = 0;
|
||||||
|
int partitions = 0;
|
||||||
|
for (int i : dist) { // 10
|
||||||
|
acc += i; // 18
|
||||||
|
if (acc > needle) { // 18 > 8 = true
|
||||||
|
acc = i; // This one isn't part of the partition we've just created = 10
|
||||||
|
if (i > needle) return false;
|
||||||
|
if (++partitions > k) { //part = 7 > 10 = false
|
||||||
|
//System.out.println("last number of partitions: "+partitions);
|
||||||
|
return false; // early break to save time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//System.out.println("i: "+i+" | acc: "+acc+" | part: "+partitions);
|
||||||
|
}
|
||||||
|
//System.out.println("last_number of partitions: "+partitions);
|
||||||
|
return partitions < k;
|
||||||
|
}
|
||||||
|
}
|
85
minimum_gap_schedulling.java
Normal file
85
minimum_gap_schedulling.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class Activity implements Comparable<Activity>
|
||||||
|
{
|
||||||
|
int start, end;
|
||||||
|
|
||||||
|
Activity(int start, int end)
|
||||||
|
{
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "["+start+","+end+"]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// Early Start
|
||||||
|
// Longest size
|
||||||
|
public int compareTo(Activity b) {
|
||||||
|
int early_start = Integer.compare(this.start, b.start);
|
||||||
|
if (early_start == 0)
|
||||||
|
return Integer.compare(b.end-b.start, this.end-this.start);
|
||||||
|
return early_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean
|
||||||
|
intersects (Activity b)
|
||||||
|
{
|
||||||
|
return this.start <= b.start ||
|
||||||
|
b.end < this.start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class
|
||||||
|
DAA013
|
||||||
|
{
|
||||||
|
public static void
|
||||||
|
main (String[] args)
|
||||||
|
{
|
||||||
|
FastScanner stdin = new FastScanner(System.in);
|
||||||
|
|
||||||
|
int M = stdin.nextInt(), // tamanho do segmento a cobrir
|
||||||
|
N = stdin.nextInt(); // qtd de segmentos
|
||||||
|
|
||||||
|
Activity[] acts = new Activity[N];
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
int l = stdin.nextInt(),
|
||||||
|
r = stdin.nextInt();
|
||||||
|
acts[i] = new Activity(l, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort them
|
||||||
|
Arrays.sort(acts);
|
||||||
|
//System.out.println(Arrays.toString(acts));
|
||||||
|
|
||||||
|
// Cobertura mínima
|
||||||
|
int end = 0;
|
||||||
|
Activity x = acts[0];
|
||||||
|
List<Activity> path = new ArrayList<>();
|
||||||
|
while (end < M)
|
||||||
|
{
|
||||||
|
for (Activity candidate : acts)
|
||||||
|
{
|
||||||
|
if (candidate.start <= end)
|
||||||
|
{
|
||||||
|
if (candidate.end >= x.end)
|
||||||
|
{
|
||||||
|
x = candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end = x.end;
|
||||||
|
path.add(x);
|
||||||
|
}
|
||||||
|
//System.out.println(path);
|
||||||
|
|
||||||
|
FastPrint.out.println(path.size());
|
||||||
|
FastPrint.out.close();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user