Website Summary Files Commits Branches @commit @diff @stats
path: root / Seminar12 / src / shortest_paths / shp_weighted.cpp
blob: 66c06f6452efa0d0ae060684dce8c1508e8da45f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "../graph_impl/weighted_graph/weighted_graph.h"
#include <algorithm>
#include <climits>
#include <iostream>
#include <queue>
#include <unordered_map>

using vertex_t       = weighted_graph::vertex_t;
using vertex_index_t = weighted_graph::vertex_index_t;
using weight_t       = weighted_graph::weight_t;

// A structure representind information which we
// obtained using dijkstra's algorithm
struct shp_info
{
	std::vector<vertex_index_t> path;
	size_t cost = 0;
};

bool relax(std::vector<int>& distance, 
           const weighted_graph& g,
           vertex_index_t reached,
           vertex_index_t current_vertex)
{
	if (distance[reached] > distance[current_vertex] + g.get_weight(current_vertex, reached))
	{
		distance[reached] = distance[current_vertex] + g.get_weight(current_vertex, reached);
		return true;
	}
	return false;
}

shp_info dijkstra_shortest_path(const weighted_graph& g, vertex_index_t from, vertex_index_t to)
{
	std::vector<int> distances(g.vertex_count(), INT_MAX);
	std::vector<vertex_index_t> parent(g.vertex_count(), -1);

	struct vertex_comparator
	{
		bool operator()(const vertex_t& lhs, const vertex_t& rhs) const
		{
			return lhs.second > rhs.second;
		}
	};

	std::priority_queue<vertex_t, std::vector<vertex_t>, vertex_comparator> q;

	q.push({from, 0});
	distances[from] = 0;
	bool found_path = false;

	while(!q.empty() && !found_path)
	{
		auto current_vertex = q.top();
		q.pop();

		if (current_vertex.first == to)
		{
			found_path = true;
			continue;
		}

		const auto& adjacent = g.adjacent(current_vertex.first);

		for(const auto& vertex : adjacent)
		{
			if(relax(distances, g, vertex.first, current_vertex.first))
			{
				q.push({vertex.first, distances[vertex.first]});
				parent[vertex.first] = current_vertex.first;
			}
		}
	}

	shp_info result;

	if(!found_path)
		return result;

	vertex_index_t it = to;
	while (true)
	{
		vertex_index_t it_parent = parent[it];
		result.path.push_back(it);
		it = it_parent;

		if(it_parent == -1)
		{
			break;
		}
	}

	result.cost = distances[to];
	std::reverse(result.path.begin(), result.path.end());

	return result;
}

int main()
{
	weighted_graph g(6, false);
	g.add_edge(0, 1, 2);
	g.add_edge(0, 2, 1);
	g.add_edge(2, 3, 6);
	g.add_edge(1, 4, 3);
	g.add_edge(3, 5, 1);
	g.add_edge(4, 5, 2);
	g.add_edge(2, 5, 4);

	auto result = dijkstra_shortest_path(g, 0, 5);

	if (result.path.empty())
	{
		std::cout << "No path found from 0 to 5.\n";
	}
	else
	{
		std::cout << "Shortest path cost: " << result.cost << "\n";
		std::cout << "Path: ";
		for (int vertex : result.path)
		{
			std::cout << vertex << " ";
		}
		std::cout << "\n";
	}

	return 0;
}