Init from KnyfSky
This commit is contained in:
commit
bd81d402be
24
CPP.cpp.snip
Normal file
24
CPP.cpp.snip
Normal file
@ -0,0 +1,24 @@
|
||||
// #define NDEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
// #include <string>
|
||||
#include <vector>
|
||||
// #include <array>
|
||||
// #include <queue>
|
||||
#include <iostream>
|
||||
// #include <map>
|
||||
// #include <math.h>
|
||||
// #include <numeric>
|
||||
// #include <tuple>
|
||||
// #include <set>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
<cursor>;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#endif
|
105
CPP/TODO/foo.cpp
Normal file
105
CPP/TODO/foo.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/* #define NDEBUG */
|
||||
|
||||
#include <stdlib.h>
|
||||
/* #include <string> */
|
||||
#include <vector>
|
||||
/* #include <array> */
|
||||
/* #include <queue> */
|
||||
#include <iostream>
|
||||
/* #include <map> */
|
||||
/* #include <math.h> */
|
||||
/* #include <numeric> */
|
||||
/* #include <tuple> */
|
||||
/* #include <set> */
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
class adjacency_list {
|
||||
public:
|
||||
size_t N;
|
||||
std::vector<std::vector<T>> adj;
|
||||
|
||||
adjacency_list (size_t n) {
|
||||
N = n;
|
||||
adj(N, std::vector<T>());
|
||||
}
|
||||
|
||||
std::vector<T> operator[](T i) { adj[i]; };
|
||||
void add_directed_edge(size_t i, size_t j) {
|
||||
adj[i].push_back(j);
|
||||
};
|
||||
void add_undirected_edge(size_t i, size_t j) {
|
||||
adj[i].push_back(j);
|
||||
adj[j].push_back(i);
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T = long>
|
||||
std::vector<std::vector<T>> floyd_warshall(std::vector<std::vector<T>> adj);
|
||||
|
||||
|
||||
int main() {
|
||||
vector<vector<int>> adj_matrix;
|
||||
auto foo = floyd_warshall(adj_matrix);
|
||||
/* floyd_warshall<int>(adj_matrix); */
|
||||
;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#endif
|
||||
|
||||
// NOTE: !!!UNTESTED!!!
|
||||
// Time complexity: O(n^3)
|
||||
// Memory complexity: O(n^2) - only for n ~ 10^3 (n ~ 10^4 results in 1524 MB of memory)
|
||||
// Input: Graph as an adjancency matrix (weight 0 => no edge)
|
||||
// Output: A distance matrix (distance std::numeric_limits<T>::max() => no path)
|
||||
#include <stdlib.h>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
template <typename T>
|
||||
std::vector<std::vector<T>> floyd_warshall(std::vector<std::vector<T>> adj) {
|
||||
size_t n = adj.size();
|
||||
std::vector<std::vector<long>> distance(n, std::vector<T>(n, 0));
|
||||
|
||||
// Initialize distance
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t j = 0; j < n; j++) {
|
||||
if (i == j) distance[i][j] = 0;
|
||||
else if (adj[i][j]) distance[i][j] = adj[i][j];
|
||||
else distance[i][j] = std::numeric_limits<T>::max();
|
||||
}
|
||||
}
|
||||
|
||||
// Find shortest distances
|
||||
for (size_t k = 0; k < n; k++) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t j = 0; j < n; j++) {
|
||||
if (distance[i][k] == std::numeric_limits<T>::max() || distance[k][j] == std::numeric_limits<T>::max())
|
||||
continue;
|
||||
distance[i][j] = std::min(distance[i][j],
|
||||
distance[i][k] + distance[k][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T = long>
|
||||
class 1D_sum_queries {
|
||||
vector<vector<T>> array;
|
||||
public:
|
||||
1D_sum_queries(size_t n) {
|
||||
|
||||
}
|
||||
std::vector<T> operator[](T i) { adj[i]; };
|
||||
}
|
37
CPP/graph_theory/floyd_warshall.cpp.snip
Normal file
37
CPP/graph_theory/floyd_warshall.cpp.snip
Normal file
@ -0,0 +1,37 @@
|
||||
// NOTE: Check the input graph for multiple edges between the same vertices! You will want to keep the shortest one
|
||||
// Time complexity: O(n^3)
|
||||
// Memory complexity: O(n^2) - only for n ~ 10^3 (n ~ 10^4 results in 1524 MB of memory)
|
||||
// Input: Graph as an adjancency matrix (weight __LONG_MAX__ => no edge)
|
||||
// Output: A distance matrix (distance __LONG_MAX__ => no path)
|
||||
vector<vector<long>> floyd_warshall(vector<vector<long>> adj) {
|
||||
size_t n = adj.size();
|
||||
vector<vector<long>> distance(n, vector<long>(n, 0));
|
||||
|
||||
// Initialize distance
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t j = 0; j < n; j++) {
|
||||
// Original floyd-warshall
|
||||
// if (i == j) distance[i][j] = 0;
|
||||
// else if (adj[i][j]) distance[i][j] = adj[i][j];
|
||||
// else distance[i][j] = __LONG_MAX__;
|
||||
|
||||
// My version
|
||||
if (i == j) distance[i][j] = 0;
|
||||
else distance[i][j] = adj[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// Find shortest distances
|
||||
for (size_t k = 0; k < n; k++) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t j = 0; j < n; j++) {
|
||||
if (distance[i][k] == __LONG_MAX__ || distance[k][j] == __LONG_MAX__)
|
||||
continue;
|
||||
distance[i][j] = min(distance[i][j],
|
||||
distance[i][k] + distance[k][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
267
CPP/graph_theory/graph.cpp.snip
Normal file
267
CPP/graph_theory/graph.cpp.snip
Normal file
@ -0,0 +1,267 @@
|
||||
// #define NDEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
template <typename T = long> class Graph;
|
||||
template <typename T = long> class WeightedGraph;
|
||||
template <typename T, typename EDGE> class BaseGraph;
|
||||
|
||||
template <typename T>
|
||||
class Graph : public BaseGraph<T, int> {
|
||||
virtual int construct_edge(int v, T w) {
|
||||
w; // Remove warning
|
||||
return v;
|
||||
}
|
||||
|
||||
virtual int get_edge_vertex(int e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
virtual T get_edge_weight(int e) {
|
||||
e; // Remove warning
|
||||
return 1;
|
||||
}
|
||||
|
||||
public:
|
||||
Graph(size_t N, size_t min_index) : BaseGraph<T, int>(N, min_index) {};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class WeightedGraph : public BaseGraph<T, std::pair<T, int>> {
|
||||
virtual std::pair<T, int> construct_edge(int v, T w) {
|
||||
return {w, v};
|
||||
}
|
||||
|
||||
virtual int get_edge_vertex(std::pair<T, int> e) {
|
||||
return e.second;
|
||||
}
|
||||
|
||||
virtual T get_edge_weight(std::pair<T, int> e) {
|
||||
return e.first;
|
||||
}
|
||||
|
||||
bool min_cut_max_flow_dfs(std::vector<std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>> &edge_pairs, std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>& path, std::vector<bool>& visited, int v, int sink, T threshold) {
|
||||
if (v == sink)
|
||||
return EXIT_SUCCESS;
|
||||
visited[v] = true;
|
||||
for (auto e : edge_pairs[v]) {
|
||||
int u = get_edge_vertex(e.first);
|
||||
int w = get_edge_weight(e.first);
|
||||
if (!visited[u] && w >= threshold) {
|
||||
bool res = min_cut_max_flow_dfs(edge_pairs, path, visited, u, sink, threshold);
|
||||
if (res == EXIT_SUCCESS) {
|
||||
path.push_back(e);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
public:
|
||||
WeightedGraph(size_t N, size_t min_index) : BaseGraph<T, std::pair<T, int>>(N, min_index) {};
|
||||
|
||||
Graph<T> get_shortest_path_graph(int from) {
|
||||
std::vector<T> best_distance = this->dijkstra(from);
|
||||
Graph<T> G(this->N, this->min_index);
|
||||
for (size_t i = this->min_index; i < this->N; i++) {
|
||||
for (auto e : this->adj[i]) {
|
||||
T w = get_edge_weight(e);
|
||||
int v = get_edge_vertex(e);
|
||||
if (best_distance[i] + w == best_distance[v])
|
||||
G.add_directed_edge(i, v);
|
||||
}
|
||||
}
|
||||
return G;
|
||||
}
|
||||
|
||||
WeightedGraph<T> get_weighted_shortest_path_graph(int from) {
|
||||
std::vector<T> best_distance = this->dijkstra(from);
|
||||
WeightedGraph<T> G(this->N, this->min_index);
|
||||
for (size_t i = this->min_index; i < this->N; i++) {
|
||||
for (auto e : this->adj[i]) {
|
||||
T w = get_edge_weight(e);
|
||||
int v = get_edge_vertex(e);
|
||||
if (best_distance[i] + w == best_distance[v])
|
||||
G.add_directed_edge(i, v, w);
|
||||
}
|
||||
}
|
||||
return G;
|
||||
}
|
||||
|
||||
// Running time: O(m^2n)
|
||||
T min_cut_max_flow(int source, int sink) {
|
||||
// TODO: Implement non-destructive version?
|
||||
// Ford-Fulkerson - "scaling algorithm" version
|
||||
std::vector<std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>> edge_pairs(this->N, std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>());
|
||||
T threshold = 0;
|
||||
for (size_t v = this->min_index; v < this->N; v++) {
|
||||
for (auto& e : this->adj[v]) {
|
||||
if (get_edge_weight(e) == 0) continue;
|
||||
threshold = threshold > get_edge_weight(e) ? threshold : get_edge_weight(e); // max(threshold, get_edge_weight(e));
|
||||
int u = get_edge_vertex(e);
|
||||
this->adj[u].push_back(construct_edge(v, 0));
|
||||
edge_pairs[v].push_back({e, this->adj[u][this->adj[u].size()-1]});
|
||||
edge_pairs[u].push_back({this->adj[u][this->adj[u].size()-1], e});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<bool> visited(this->N, false);
|
||||
std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>> path;
|
||||
while (true) {
|
||||
bool res = min_cut_max_flow_dfs(edge_pairs, path, visited, source, sink, threshold);
|
||||
if (res == EXIT_SUCCESS) {
|
||||
T path_max_flow = std::numeric_limits<T>::max();
|
||||
for (auto e : path)
|
||||
path_max_flow = path_max_flow < get_edge_weight(e.first) ? path_max_flow : get_edge_weight(e.first);
|
||||
// min(path_max_flow, get_edge_weight(e.first));
|
||||
for (auto e : path) {
|
||||
e.first = construct_edge(get_edge_vertex(e.first), get_edge_weight(e.first)-threshold);
|
||||
e.second = construct_edge(get_edge_vertex(e.second), get_edge_weight(e.second)+threshold);
|
||||
}
|
||||
} else {
|
||||
if (threshold == 1)
|
||||
break; // Done!
|
||||
threshold /= 2;
|
||||
}
|
||||
std::fill(visited.begin(), visited.end(), false);
|
||||
path.clear();
|
||||
}
|
||||
|
||||
T max_flow = 0;
|
||||
for (auto e : this->adj[sink]) {
|
||||
max_flow += get_edge_weight(e);
|
||||
}
|
||||
|
||||
return max_flow;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename EDGE>
|
||||
class BaseGraph {
|
||||
std::vector<int> top_sort;
|
||||
int contains_cycles = 0; // 0 = unknown, 1 = yes, 2 = no
|
||||
bool contains_negative_edge_weight = false;
|
||||
|
||||
virtual int get_edge_vertex(EDGE) = 0;
|
||||
virtual T get_edge_weight(EDGE) = 0;
|
||||
virtual EDGE construct_edge(int vertex, T w) = 0;
|
||||
|
||||
bool topological_sort_dfs(std::vector<int8_t>& status, int v, std::vector<int>& top_sort) {
|
||||
if (status[v] == 1)
|
||||
return EXIT_FAILURE;
|
||||
if (status[v] == 0) {
|
||||
status[v] = 1;
|
||||
for (auto e : adj[v]) {
|
||||
bool res = topological_sort_dfs(status, get_edge_vertex(e), top_sort);
|
||||
if (res == EXIT_FAILURE)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
status[v] = 2;
|
||||
top_sort.push_back(v);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void do_topological_sort() {
|
||||
std::vector<int8_t> status(N, 0);
|
||||
std::vector<int> top_sort = std::vector<int>();
|
||||
for (size_t i = min_index; i < N; i++) {
|
||||
bool res = topological_sort_dfs(status, i, top_sort);
|
||||
if (res == EXIT_FAILURE) {
|
||||
contains_cycles = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
contains_cycles = 2;
|
||||
std::reverse(top_sort.begin(), top_sort.end());
|
||||
this->top_sort = top_sort;
|
||||
}
|
||||
|
||||
public:
|
||||
size_t N;
|
||||
size_t min_index;
|
||||
std::vector<std::vector<EDGE>> adj;
|
||||
|
||||
BaseGraph(size_t N, size_t min_index) {
|
||||
N += min_index;
|
||||
this->N = N;
|
||||
this->min_index = min_index;
|
||||
adj = std::vector<std::vector<EDGE>>(N, std::vector<EDGE>());
|
||||
}
|
||||
|
||||
void add_directed_edge(int from, int to, T w = 1) {
|
||||
adj[from].push_back(construct_edge(to, w));
|
||||
contains_cycles = 0;
|
||||
if (w < 0)
|
||||
contains_negative_edge_weight = true;
|
||||
}
|
||||
|
||||
void add_undirected_edge(size_t a, size_t b, T w = 1) {
|
||||
adj[a].push_back(construct_edge(b, w));
|
||||
adj[b].push_back(construct_edge(a, w));
|
||||
contains_cycles = 0;
|
||||
if (w < 0)
|
||||
contains_negative_edge_weight = true;
|
||||
}
|
||||
|
||||
std::vector<EDGE> get(int v) {
|
||||
return adj[v];
|
||||
}
|
||||
|
||||
std::vector<int> topological_sort() {
|
||||
if (contains_cycles != 2)
|
||||
std::cerr << "Check for cycles first!" << std::endl;
|
||||
return top_sort;
|
||||
}
|
||||
|
||||
bool has_cycles() {
|
||||
if (contains_cycles == 0)
|
||||
do_topological_sort();
|
||||
return contains_cycles == 1;
|
||||
}
|
||||
|
||||
std::vector<T> count_paths(int from) {
|
||||
if (contains_cycles != 2)
|
||||
std::cerr << "Check for cycles first!" << std::endl;
|
||||
std::vector<T> paths(N, 0);
|
||||
for (auto v : top_sort) {
|
||||
T p = 0;
|
||||
if (v == from) p++;
|
||||
for (auto e : adj[v])
|
||||
p += paths[get_edge_vertex(e)];
|
||||
paths[v] = p;
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
std::vector<T> dijkstra(int from) {
|
||||
if (contains_negative_edge_weight)
|
||||
std::cerr << "Dijkstra only works if the graph doesn't contain any negative edge weights" << std::endl;
|
||||
std::vector<T> distance(N, std::numeric_limits<T>::max());
|
||||
distance[from] = 0;
|
||||
std::vector<bool> processed(N, false);
|
||||
std::priority_queue<std::pair<T, int>> q;
|
||||
q.push({0, from});
|
||||
while (!q.empty()) {
|
||||
int v = q.top().second; q.pop();
|
||||
if (processed[v]) continue;
|
||||
processed[v] = true;
|
||||
for (auto e : adj[v]) {
|
||||
int u = get_edge_vertex(e);
|
||||
T w = get_edge_weight(e);
|
||||
if (distance[v] + w < distance[u]) {
|
||||
distance[u] = distance[v] + w;
|
||||
q.push({-distance[u], u});
|
||||
}
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
};
|
BIN
CPP/graph_theory/test/test
Normal file
BIN
CPP/graph_theory/test/test
Normal file
Binary file not shown.
372
CPP/graph_theory/test/test.cpp
Normal file
372
CPP/graph_theory/test/test.cpp
Normal file
@ -0,0 +1,372 @@
|
||||
// #define NDEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
// #include <string>
|
||||
#include <vector>
|
||||
// #include <array>
|
||||
// #include <queue>
|
||||
#include <iostream>
|
||||
// #include <map>
|
||||
// #include <math.h>
|
||||
// #include <numeric>
|
||||
// #include <tuple>
|
||||
// #include <set>
|
||||
|
||||
|
||||
// #define NDEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
template <typename T = long> class Graph;
|
||||
template <typename T = long> class WeightedGraph;
|
||||
template <typename T, typename EDGE> class BaseGraph;
|
||||
|
||||
template <typename T>
|
||||
class Graph : public BaseGraph<T, int> {
|
||||
virtual int construct_edge(int v, T w) {
|
||||
w; // Remove warning
|
||||
return v;
|
||||
}
|
||||
|
||||
virtual int get_edge_vertex(int e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
virtual T get_edge_weight(int e) {
|
||||
e; // Remove warning
|
||||
return 1;
|
||||
}
|
||||
|
||||
public:
|
||||
Graph(size_t N, size_t min_index) : BaseGraph<T, int>(N, min_index) {};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class WeightedGraph : public BaseGraph<T, std::pair<T, int>> {
|
||||
virtual std::pair<T, int> construct_edge(int v, T w) {
|
||||
return {w, v};
|
||||
}
|
||||
|
||||
virtual int get_edge_vertex(std::pair<T, int> e) {
|
||||
return e.second;
|
||||
}
|
||||
|
||||
virtual T get_edge_weight(std::pair<T, int> e) {
|
||||
return e.first;
|
||||
}
|
||||
|
||||
bool min_cut_max_flow_dfs(std::vector<std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>> &edge_pairs, std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>& path, std::vector<bool>& visited, int v, int sink, T threshold) {
|
||||
if (v == sink)
|
||||
return EXIT_SUCCESS;
|
||||
visited[v] = true;
|
||||
for (auto e : edge_pairs[v]) {
|
||||
int u = get_edge_vertex(e.first);
|
||||
int w = get_edge_weight(e.first);
|
||||
if (!visited[u] && w >= threshold) {
|
||||
bool res = min_cut_max_flow_dfs(edge_pairs, path, visited, u, sink, threshold);
|
||||
if (res == EXIT_SUCCESS) {
|
||||
path.push_back(e);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
public:
|
||||
WeightedGraph(size_t N, size_t min_index) : BaseGraph<T, std::pair<T, int>>(N, min_index) {};
|
||||
|
||||
Graph<T> get_shortest_path_graph(int from) {
|
||||
std::vector<T> best_distance = this->dijkstra(from);
|
||||
Graph<T> G(this->N, this->min_index);
|
||||
for (size_t i = this->min_index; i < this->N; i++) {
|
||||
for (auto e : this->adj[i]) {
|
||||
T w = get_edge_weight(e);
|
||||
int v = get_edge_vertex(e);
|
||||
if (best_distance[i] + w == best_distance[v])
|
||||
G.add_directed_edge(i, v);
|
||||
}
|
||||
}
|
||||
return G;
|
||||
}
|
||||
|
||||
WeightedGraph<T> get_weighted_shortest_path_graph(int from) {
|
||||
std::vector<T> best_distance = this->dijkstra(from);
|
||||
WeightedGraph<T> G(this->N, this->min_index);
|
||||
for (size_t i = this->min_index; i < this->N; i++) {
|
||||
for (auto e : this->adj[i]) {
|
||||
T w = get_edge_weight(e);
|
||||
int v = get_edge_vertex(e);
|
||||
if (best_distance[i] + w == best_distance[v])
|
||||
G.add_directed_edge(i, v, w);
|
||||
}
|
||||
}
|
||||
return G;
|
||||
}
|
||||
|
||||
// Running time: O(m^2n)
|
||||
T min_cut_max_flow(int source, int sink) {
|
||||
// TODO: Implement non-destructive version?
|
||||
// Ford-Fulkerson - "scaling algorithm" version
|
||||
std::vector<std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>> edge_pairs(this->N, std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>>());
|
||||
T threshold = 0;
|
||||
for (size_t v = this->min_index; v < this->N; v++) {
|
||||
for (auto& e : this->adj[v]) {
|
||||
if (get_edge_weight(e) == 0) continue;
|
||||
threshold = threshold > get_edge_weight(e) ? threshold : get_edge_weight(e); // max(threshold, get_edge_weight(e));
|
||||
int u = get_edge_vertex(e);
|
||||
this->adj[u].push_back(construct_edge(v, 0));
|
||||
edge_pairs[v].push_back({e, this->adj[u][this->adj[u].size()-1]});
|
||||
edge_pairs[u].push_back({this->adj[u][this->adj[u].size()-1], e});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<bool> visited(this->N, false);
|
||||
std::vector<std::pair<std::pair<T, int>&, std::pair<T, int>&>> path;
|
||||
while (true) {
|
||||
bool res = min_cut_max_flow_dfs(edge_pairs, path, visited, source, sink, threshold);
|
||||
if (res == EXIT_SUCCESS) {
|
||||
T path_max_flow = std::numeric_limits<T>::max();
|
||||
for (auto e : path)
|
||||
path_max_flow = path_max_flow < get_edge_weight(e.first) ? path_max_flow : get_edge_weight(e.first);
|
||||
// min(path_max_flow, get_edge_weight(e.first));
|
||||
for (auto e : path) {
|
||||
e.first = construct_edge(get_edge_vertex(e.first), get_edge_weight(e.first)-threshold);
|
||||
e.second = construct_edge(get_edge_vertex(e.second), get_edge_weight(e.second)+threshold);
|
||||
}
|
||||
} else {
|
||||
if (threshold == 1)
|
||||
break; // Done!
|
||||
threshold /= 2;
|
||||
}
|
||||
std::fill(visited.begin(), visited.end(), false);
|
||||
path.clear();
|
||||
}
|
||||
|
||||
T max_flow = 0;
|
||||
for (auto e : this->adj[sink]) {
|
||||
max_flow += get_edge_weight(e);
|
||||
}
|
||||
|
||||
return max_flow;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename EDGE>
|
||||
class BaseGraph {
|
||||
std::vector<int> top_sort;
|
||||
int contains_cycles = 0; // 0 = unknown, 1 = yes, 2 = no
|
||||
bool contains_negative_edge_weight = false;
|
||||
|
||||
virtual int get_edge_vertex(EDGE) = 0;
|
||||
virtual T get_edge_weight(EDGE) = 0;
|
||||
virtual EDGE construct_edge(int vertex, T w) = 0;
|
||||
|
||||
bool topological_sort_dfs(std::vector<int8_t>& status, int v, std::vector<int>& top_sort) {
|
||||
if (status[v] == 1)
|
||||
return EXIT_FAILURE;
|
||||
if (status[v] == 0) {
|
||||
status[v] = 1;
|
||||
for (auto e : adj[v]) {
|
||||
bool res = topological_sort_dfs(status, get_edge_vertex(e), top_sort);
|
||||
if (res == EXIT_FAILURE)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
status[v] = 2;
|
||||
top_sort.push_back(v);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void do_topological_sort() {
|
||||
std::vector<int8_t> status(N, 0);
|
||||
std::vector<int> top_sort = std::vector<int>();
|
||||
for (size_t i = min_index; i < N; i++) {
|
||||
bool res = topological_sort_dfs(status, i, top_sort);
|
||||
if (res == EXIT_FAILURE) {
|
||||
contains_cycles = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
contains_cycles = 2;
|
||||
std::reverse(top_sort.begin(), top_sort.end());
|
||||
this->top_sort = top_sort;
|
||||
}
|
||||
|
||||
public:
|
||||
size_t N;
|
||||
size_t min_index;
|
||||
std::vector<std::vector<EDGE>> adj;
|
||||
|
||||
BaseGraph(size_t N, size_t min_index) {
|
||||
N += min_index;
|
||||
this->N = N;
|
||||
this->min_index = min_index;
|
||||
adj = std::vector<std::vector<EDGE>>(N, std::vector<EDGE>());
|
||||
}
|
||||
|
||||
void add_directed_edge(int from, int to, T w = 1) {
|
||||
adj[from].push_back(construct_edge(to, w));
|
||||
contains_cycles = 0;
|
||||
if (w < 0)
|
||||
contains_negative_edge_weight = true;
|
||||
}
|
||||
|
||||
void add_undirected_edge(size_t a, size_t b, T w = 1) {
|
||||
adj[a].push_back(construct_edge(b, w));
|
||||
adj[b].push_back(construct_edge(a, w));
|
||||
contains_cycles = 0;
|
||||
if (w < 0)
|
||||
contains_negative_edge_weight = true;
|
||||
}
|
||||
|
||||
std::vector<EDGE> get(int v) {
|
||||
return adj[v];
|
||||
}
|
||||
|
||||
std::vector<int> topological_sort() {
|
||||
if (contains_cycles != 2)
|
||||
std::cerr << "Check for cycles first!" << std::endl;
|
||||
return top_sort;
|
||||
}
|
||||
|
||||
bool has_cycles() {
|
||||
if (contains_cycles == 0)
|
||||
do_topological_sort();
|
||||
return contains_cycles == 1;
|
||||
}
|
||||
|
||||
std::vector<T> count_paths(int from) {
|
||||
if (contains_cycles != 2)
|
||||
std::cerr << "Check for cycles first!" << std::endl;
|
||||
std::vector<T> paths(N, 0);
|
||||
for (auto v : top_sort) {
|
||||
T p = 0;
|
||||
if (v == from) p++;
|
||||
for (auto e : adj[v])
|
||||
p += paths[get_edge_vertex(e)];
|
||||
paths[v] = p;
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
std::vector<T> dijkstra(int from) {
|
||||
if (contains_negative_edge_weight)
|
||||
std::cerr << "Dijkstra only works if the graph doesn't contain any negative edge weights" << std::endl;
|
||||
std::vector<T> distance(N, std::numeric_limits<T>::max());
|
||||
distance[from] = 0;
|
||||
std::vector<bool> processed(N, false);
|
||||
std::priority_queue<std::pair<T, int>> q;
|
||||
q.push({0, from});
|
||||
while (!q.empty()) {
|
||||
int v = q.top().second; q.pop();
|
||||
if (processed[v]) continue;
|
||||
processed[v] = true;
|
||||
for (auto e : adj[v]) {
|
||||
int u = get_edge_vertex(e);
|
||||
T w = get_edge_weight(e);
|
||||
if (distance[v] + w < distance[u]) {
|
||||
distance[u] = distance[v] + w;
|
||||
q.push({-distance[u], u});
|
||||
}
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
// TODO: SEGFAULT
|
||||
// WeightedGraph G(6, 1);
|
||||
// G.add_directed_edge(1, 2, 5);
|
||||
// G.add_directed_edge(1, 4, 4);
|
||||
// G.add_directed_edge(4, 2, 3);
|
||||
// G.add_directed_edge(2, 3, 6);
|
||||
// G.add_directed_edge(4, 5, 1);
|
||||
// G.add_directed_edge(3, 5, 8);
|
||||
// G.add_directed_edge(3, 6, 5);
|
||||
// G.add_directed_edge(5, 6, 2);
|
||||
|
||||
// cout << "foo" << endl;
|
||||
// cout << G.min_cut_max_flow(1, 6) << endl;
|
||||
|
||||
// // Works! (Probably)
|
||||
// WeightedGraph G(6, 1);
|
||||
// G.add_directed_edge(1, 2, 5);
|
||||
// G.add_directed_edge(4, 1, 4);
|
||||
// G.add_directed_edge(4, 5, 4);
|
||||
// G.add_directed_edge(5, 2, 4);
|
||||
// G.add_directed_edge(5, 3, 4);
|
||||
// G.add_directed_edge(2, 3, 4);
|
||||
// G.add_directed_edge(3, 6, 4);
|
||||
|
||||
// cout << "foo" << endl;
|
||||
// bool cycles = G.has_cycles();
|
||||
// cout << "Has cycles: " << cycles << endl;
|
||||
// vector<int> top = G.topological_sort();
|
||||
// for (auto i : top)
|
||||
// cout << i << " ";
|
||||
// cout << endl;
|
||||
|
||||
// // Works! (Probably)
|
||||
// WeightedGraph G(6, 1);
|
||||
// G.add_directed_edge(1, 2, 5);
|
||||
// G.add_directed_edge(1, 4, 4);
|
||||
// G.add_directed_edge(5, 1, 4);
|
||||
// G.add_directed_edge(4, 5, 4);
|
||||
// G.add_directed_edge(5, 2, 4);
|
||||
// G.add_directed_edge(5, 3, 4);
|
||||
// G.add_directed_edge(2, 3, 4);
|
||||
// G.add_directed_edge(3, 6, 4);
|
||||
|
||||
// cout << "foo" << endl;
|
||||
// bool cycles = G.has_cycles();
|
||||
// cout << "Has cycles: " << cycles << endl;
|
||||
|
||||
// // Works! (Probably)
|
||||
// Graph G(6, 1);
|
||||
// G.add_directed_edge(1, 2);
|
||||
// G.add_directed_edge(4, 1);
|
||||
// G.add_directed_edge(4, 5);
|
||||
// G.add_directed_edge(5, 2);
|
||||
// G.add_directed_edge(5, 3);
|
||||
// G.add_directed_edge(2, 3);
|
||||
// G.add_directed_edge(3, 6);
|
||||
|
||||
// cout << "foo" << endl;
|
||||
// bool cycles = G.has_cycles();
|
||||
// cout << "Has cycles: " << cycles << endl;
|
||||
// vector<int> top = G.topological_sort();
|
||||
// for (auto i : top)
|
||||
// cout << i << " ";
|
||||
// cout << endl;
|
||||
|
||||
// Works! (Probably)
|
||||
WeightedGraph G(6, 1);
|
||||
G.add_directed_edge(1, 2, 5);
|
||||
G.add_directed_edge(4, 1, 4);
|
||||
G.add_directed_edge(4, 5, 4);
|
||||
G.add_directed_edge(5, 2, 4);
|
||||
G.add_directed_edge(5, 3, 4);
|
||||
G.add_directed_edge(2, 3, 4);
|
||||
G.add_directed_edge(3, 6, 4);
|
||||
|
||||
cout << "foo" << endl;
|
||||
bool cycles = G.has_cycles();
|
||||
cout << "Has cycles: " << cycles << endl;
|
||||
vector<long> dist = G.dijkstra(1);
|
||||
for (int i = 1; i <= 6; i++)
|
||||
cout << i << " " << dist[i] << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
25
CPP/hpc/dmalloc_2d.c.snip
Normal file
25
CPP/hpc/dmalloc_2d.c.snip
Normal file
@ -0,0 +1,25 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
double** dmalloc_2d(int m, int n);
|
||||
void dfree_2d(double **A);
|
||||
|
||||
// allocate a double-precision m x n matrix
|
||||
double** dmalloc_2d(int m, int n) {
|
||||
if (m <= 0 || n <= 0) return NULL;
|
||||
double **A = malloc(m * sizeof(double *));
|
||||
if (A == NULL) return NULL;
|
||||
A[0] = malloc(m*n*sizeof(double));
|
||||
if (A[0] == NULL) {
|
||||
free(A);
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 1; i < m; i++)
|
||||
A[i] = A[0] + i * n;
|
||||
return A;
|
||||
}
|
||||
|
||||
// de-allocating memory, allocated with dmalloc_2d
|
||||
void dfree_2d(double **A) {
|
||||
free(A[0]);
|
||||
free(A);
|
||||
}
|
6
CPP/hpc/include_cblas.c.snip
Normal file
6
CPP/hpc/include_cblas.c.snip
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
#include <Accelerate/Accelerate.h>
|
||||
#else
|
||||
#include <cblas.h>
|
||||
#endif
|
142
CPP/range_queries/SegmentTree.cpp.snip
Normal file
142
CPP/range_queries/SegmentTree.cpp.snip
Normal file
@ -0,0 +1,142 @@
|
||||
#define NDEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
template <typename T = long> class SegmentTree;
|
||||
template <typename T = long> class SumSegmentTree;
|
||||
template <typename T = long> class MinSegmentTree;
|
||||
template <typename T = long> class MaxSegmentTree;
|
||||
template <typename T = long> class DifferenceSegmentTree;
|
||||
|
||||
template <typename T>
|
||||
class SumSegmentTree : public SegmentTree<T> {
|
||||
virtual T cmp (T a, T b) override {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
public:
|
||||
SumSegmentTree(size_t N) : SegmentTree<T>(N, 0) {};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MinSegmentTree : public SegmentTree<T> {
|
||||
virtual T cmp (T a, T b) override {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
public:
|
||||
MinSegmentTree(size_t N) : SegmentTree<T>(N, std::numeric_limits<T>::max()) {};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MaxSegmentTree : public SegmentTree<T> {
|
||||
virtual T cmp (T a, T b) override {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
public:
|
||||
MaxSegmentTree(size_t N) : SegmentTree<T>(N, std::numeric_limits<T>::min()) {};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class DifferenceSegmentTree : public SegmentTree<T> {
|
||||
virtual T cmp (T a, T b) override {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void add(size_t i, T val) override {
|
||||
this->set(i, this->get(i) + val);
|
||||
if (i != this->N-1)
|
||||
this->set(i+1, this->get(i+1) - val);
|
||||
}
|
||||
|
||||
void add_range(size_t i, size_t j, T val) {
|
||||
this->set(i, this->get(i) + val);
|
||||
if (j+1 != this->N)
|
||||
this->set(j+1, this->get(j+1)-val);
|
||||
}
|
||||
|
||||
DifferenceSegmentTree(size_t N) : SegmentTree<T>(N, 0) {};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SegmentTree {
|
||||
const T unit;
|
||||
virtual T cmp (T a, T b) = 0;
|
||||
std::vector<T> arr;
|
||||
|
||||
public:
|
||||
size_t N;
|
||||
|
||||
void print() {
|
||||
size_t newline = 2;
|
||||
for (size_t i = 1; i < 2*N; i++) {
|
||||
std::cout << arr[i] << " ";
|
||||
if (i == newline-1) {
|
||||
std::cout << std::endl;
|
||||
newline *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SegmentTree(size_t N, T unit) : unit(unit) {
|
||||
this->N = N;
|
||||
// Initialize the array to the size of the smallest power of two greater than N
|
||||
size_t exp = 0;
|
||||
while (N != 0) {
|
||||
N = N >> 1;
|
||||
exp++;
|
||||
}
|
||||
if ((size_t)(1 << (exp-1)) == this->N)
|
||||
arr = std::vector<T>(this->N*2, unit);
|
||||
else
|
||||
arr = std::vector<T>(1 << (exp+1), unit);
|
||||
}
|
||||
|
||||
T get(size_t i) {
|
||||
#ifndef NDEBUG
|
||||
if (i >= N)
|
||||
std::cerr << "Tried accessing index " << i << " out of " << N-1 << " (remember, 0-indexing)" << std::endl;
|
||||
#endif
|
||||
return arr[i+N];
|
||||
}
|
||||
/* T operator[](size_t i) { get(i); }; */
|
||||
|
||||
virtual void set(size_t i, T val) {
|
||||
update_field(i, val);
|
||||
}
|
||||
|
||||
void update_field(size_t i, T val) {
|
||||
#ifndef NDEBUG
|
||||
if (i >= N)
|
||||
std::cerr << "Tried updating index " << i << " out of " << N-1 << " (remember, 0-indexing)" << std::endl;
|
||||
#endif
|
||||
i += N; // Put the index at the leaf nodes/original array
|
||||
arr[i] = val;
|
||||
for (i /= 2; i >= 1; i /= 2)
|
||||
arr[i] = cmp(arr[i*2], arr[i*2+1]);
|
||||
}
|
||||
|
||||
virtual void add(size_t i, T val) {
|
||||
set(i, val + get(i));
|
||||
}
|
||||
|
||||
T query(size_t a, size_t b) {
|
||||
#ifndef NDEBUG
|
||||
if (a > N || b > N || a > b)
|
||||
std::cerr << "Tried querying the range: [" << a << ", " << b << "]" << " of max index " << N-1 << std::endl;
|
||||
#endif
|
||||
a += N; b += N;
|
||||
size_t val = unit;
|
||||
while (a <= b) {
|
||||
if (a % 2 == 1) val = cmp(val, arr[a++]);
|
||||
if (b % 2 == 0) val = cmp(val, arr[b--]);
|
||||
a /= 2; b /= 2;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
12
CPP/utility/prime_sieve.cpp.snip
Normal file
12
CPP/utility/prime_sieve.cpp.snip
Normal file
@ -0,0 +1,12 @@
|
||||
vector<int> prime_sieve(int n) {
|
||||
vector<bool> is_prime(n+1, true);
|
||||
is_prime[0] = is_prime[1] = false;
|
||||
vector<int> primes;
|
||||
for (int i = 2; i <= n; i++) {
|
||||
if (!is_prime[i]) continue;
|
||||
primes.push_back(i);
|
||||
for (int j = i; j <= n; j += i)
|
||||
is_prime[j] = false;
|
||||
}
|
||||
return primes;
|
||||
}
|
8
HTML.html.snip
Normal file
8
HTML.html.snip
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
18
Markdown.md.snip
Normal file
18
Markdown.md.snip
Normal file
@ -0,0 +1,18 @@
|
||||
<style>
|
||||
.markdown-body { overflow: visible }
|
||||
</style>
|
||||
|
||||
<div style="overflow: visible">
|
||||
|
||||
<div style="position: sticky; float: right; top: 90%; z-index: 1000; font-size: 80px"><a href="#table-of-contents">⮉</a></div>
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
# Table of Contents
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
|
||||
|
||||
<!-- Keep this div at the bottom of the document -->
|
||||
</div>
|
4
install_configfiles.sh
Normal file
4
install_configfiles.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
mkdir -p ~/.config/nvim;
|
||||
rm -df ~/.config/nvim/snippets;
|
||||
ln -s ~/Nextcloud/configfiles/vim/snippets ~/.config/nvim/snippets;
|
29
julia_OR.jl.snip
Normal file
29
julia_OR.jl.snip
Normal file
@ -0,0 +1,29 @@
|
||||
using JuMP, GLPK
|
||||
|
||||
profit = [5, 3, 2, 7, 4]
|
||||
weight = [2, 8, 4, 2, 5]
|
||||
capacity = 10
|
||||
|
||||
model = Model(GLPK.Optimizer)
|
||||
|
||||
n = 5
|
||||
@variable(model, x[1:n], Bin) # Binary
|
||||
@variable(model, y[1:n], Int) # Integer
|
||||
@variable(model, z[1:n]) # Continuous
|
||||
|
||||
@objective(model, Max, sum(profit[i]*x[i] for i=1:n))
|
||||
@constraint(model, sum(weight[i]*x[i] for i=1:n) <= capacity)
|
||||
@constraint(model, [i=1:n], x[i] <= 1) # unnecessary, just to include this syntax in the example
|
||||
|
||||
JuMP.optimize!(model)
|
||||
|
||||
if termination_status(model) == MOI.OPTIMAL
|
||||
println("Objective is: ", JuMP.objective_value(model))
|
||||
print("Solution is:")
|
||||
for i=1:n
|
||||
print(" ", JuMP.value(x[i]))
|
||||
end
|
||||
println()
|
||||
else
|
||||
println("Optimise was not successful. Return code ", termination_status(model))
|
||||
end
|
17
latex.tex.snip
Normal file
17
latex.tex.snip
Normal file
@ -0,0 +1,17 @@
|
||||
\documentclass[11pt]{article}
|
||||
\usepackage{../../../Texpreambles/JRPreamble}
|
||||
\DTMsavedate{mydate}{2022-9-5}% chktex 8
|
||||
|
||||
\usepackage{listings}
|
||||
|
||||
\begin{document}
|
||||
\selectlanguage{british}
|
||||
|
||||
\begin{center}
|
||||
\Huge My Course: Assignment 1 \\
|
||||
\Large Jonas Ryssel \\
|
||||
\Large s184009 \\
|
||||
\Large \DTMusedate{mydate}
|
||||
\end{center}
|
||||
|
||||
\end{document}
|
9
rust/unit_test.rs.snip
Normal file
9
rust/unit_test.rs.snip
Normal file
@ -0,0 +1,9 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn my_test() {
|
||||
assert_eq!(add(1, 2), 3);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user