Skip to content

Instantly share code, notes, and snippets.

@adrian17
Last active August 13, 2019 12:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adrian17/f3554dbe0c0b65b7ebab37ea5897745a to your computer and use it in GitHub Desktop.
Save adrian17/f3554dbe0c0b65b7ebab37ea5897745a to your computer and use it in GitHub Desktop.
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>
#include <unordered_set>
#include <chrono>
using namespace std::chrono;
using std::cout;
using std::endl;
class Dynamic_Graph {
public:
struct Edge {
unsigned int connection_to;
int weight;
Edge(int weight, unsigned int connection_to) : connection_to(connection_to), weight(weight) {}
};
Dynamic_Graph(unsigned int n) : vertex_count(n) {
edges.resize(n);
}
void addEdge(unsigned int from, unsigned int to, int weight) {
edges[from].push_back(Edge(weight, to));
}
unsigned int get_vertex_count() const { return vertex_count; }
const std::vector<Edge>& iter_edges(unsigned id) const { return edges[id]; }
int weight_of(unsigned int from, unsigned int connected_to) {
for (auto &edge : edges[from]) {
if (edge.connection_to == connected_to) {
return edge.weight;
}
}
return -1;
}
private:
std::vector<std::vector<Edge>> edges;
const unsigned int vertex_count;
};
void randomize_graph(Dynamic_Graph& G, int num_of_edges)
{
srand(7);
const unsigned int graph_size = G.get_vertex_count();
const unsigned int iterations = num_of_edges;
for (unsigned int i = 0; i < iterations; i++)
{
unsigned a = rand() % graph_size;
unsigned b = rand() % graph_size;
G.addEdge(a, b, rand() % 1000);
}
}
struct result_props {
int distance = 0;
int last = -1;
};
void DjikstraAlgoritm(const Dynamic_Graph& graph, std::vector<result_props> &result, unsigned start) {
for (size_t i = 0; i < graph.get_vertex_count(); i++)
result[i].distance = 2000000;
result[start].distance = 0;
auto compare_paths = [&](unsigned p1, unsigned p2){ return result[p1].distance > result[p2].distance; };
std::vector<unsigned> doSprawdzenia = { start };
std::unordered_set<unsigned> sprawdzone;
while (!doSprawdzenia.empty()) {
//znajdz wierzcholek o najmniejszej wartosci dis (ver)
auto ver = doSprawdzenia.back();
doSprawdzenia.pop_back();
sprawdzone.emplace(ver);
for (auto edge : graph.iter_edges(ver))
{
if (sprawdzone.count(edge.connection_to) > 0)
continue;
auto existing = std::find(doSprawdzenia.begin(), doSprawdzenia.end(), edge.connection_to);
if (existing != doSprawdzenia.end()) {
// jeśli juz jest w priority queue, sprawdz czy ta krawedz jest lepsza.
// Jesli tak, to zmieniamy priorytet (przez usunięcie i ponowne dodanie).
// Jesli nie, to ignorujemy i szukamy dalej.
if (result[edge.connection_to].distance > result[ver].distance + edge.weight) {
doSprawdzenia.erase(existing);
} else {
continue;
}
}
result[edge.connection_to].distance = result[ver].distance + edge.weight;
result[edge.connection_to].last = ver;
doSprawdzenia.insert(
std::lower_bound(doSprawdzenia.begin(), doSprawdzenia.end(), edge.connection_to, compare_paths),
edge.connection_to
);
}
}
}
int main()
{
//Losowy graf z 40000 wierzcholkami i 300000 krawedziami
Dynamic_Graph graph(40000);
graph.addEdge(0, 7, 1);//a->h
graph.addEdge(0, 4, 1);//a->e
graph.addEdge(1, 2, 2);//b->c
graph.addEdge(3, 0, 4);//d->a
graph.addEdge(3, 7, 1);//d->h
graph.addEdge(4, 5, 3);//e->f
graph.addEdge(5, 6, 7);//f->g
graph.addEdge(5, 8, 1);//f->i
graph.addEdge(5, 1, 1);//f->b
graph.addEdge(5, 2, 3);//f->c
graph.addEdge(7, 8, 9);//h->i
graph.addEdge(8, 9, 2);//i->j
graph.addEdge(9, 6, 1);//j->g
randomize_graph(graph, 300000);
auto vertex1 = 5;
auto vertex2 = 4;
cout << "Weight: " << graph.weight_of(vertex2, vertex1) << endl;
cout << "from:" << vertex2 << endl;
cout << "to: " << vertex1 << endl;
cout << endl;
cout << "All edges from " << vertex1 << endl;
for (auto i : graph.iter_edges(vertex1))
{
cout << i.weight << endl;
}
std::vector<result_props> result(graph.get_vertex_count());
DjikstraAlgoritm(graph, result, 3);
cout << "Shortest path form 3 to: " << endl;
for (size_t i = 0; i < graph.get_vertex_count(); i++)
{
if (result[i].distance == 2000000) {
continue;
}
cout << i << " " << result[i].distance << "\t";
if (i != 3) {
int id = result[i].last;
while (id != 3) {
cout << id << " ";
id = result[id].last;
}
}
cout << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment