This commit is contained in:
Diogo Cordeiro 2021-02-03 23:38:26 +00:00
parent 6fef06fdef
commit fc5aee5646
18 changed files with 1532 additions and 1 deletions

83
Couple.java Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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();
}
}

View File

@ -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
View 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;
}
}
}

View 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
View 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
View 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
View 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
View 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;
}
}

View 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();
}
}