AdventOfCode2024/include/aoc/common/WeightedEdgeGraph.hpp

114 lines
3.3 KiB
C++

// Solutions to the Advent Of Code 2024.
// Copyright (C) 2025 Stefan Müller
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <iterator>
#include <vector>
#include <aoc/common/VertexEdgeIncidence.hpp>
class WeightedEdgeGraph
{
public:
WeightedEdgeGraph();
int addVertex(const int weight);
void addEdge(const int vertex1, const int vertex2, const int weight);
int getVertexWeight(const int vertex) const;
int getEdgeWeight(const int edge) const;
std::vector<int> dijkstra(const int source) const;
struct Incidence
{
public:
Incidence(const int vertex, const int edge)
: vertex{ vertex }, edge{ edge }
{
}
int vertex;
int edge;
};
struct NeighborIterator
{
public:
// Iterator traits.
using difference_type = std::ptrdiff_t;
using value_type = Incidence;
using pointer = const value_type*;
using reference = const value_type&;
using iterator_category = std::forward_iterator_tag;
NeighborIterator(const WeightedEdgeGraph& graph, const int vertex)
: graph_{ graph }, incidence_{ -1 }, value_{ -1, -1 }
{
if (vertex >= 0 && vertex < graph_.firstVertexIncidences_.size())
{
setIncidence(graph_.firstVertexIncidences_[vertex]);
}
};
NeighborIterator& operator++()
{
if (incidence_ >= 0)
{
setIncidence(graph_.vertexEdgeIncidences_[incidence_].next);
}
return *this;
}
NeighborIterator operator++(int)
{
NeighborIterator it = *this;
++(*this);
return it;
}
bool operator==(NeighborIterator other) const
{
return incidence_ == other.incidence_;
}
bool operator!=(NeighborIterator other) const
{
return !(*this == other);
}
const reference operator*() const
{
return value_;
}
const pointer operator->() const
{
return &value_;
}
private:
const WeightedEdgeGraph& graph_;
int incidence_;
value_type value_;
void setIncidence(const int incidence)
{
incidence_ = incidence;
if (incidence_ >= 0)
{
value_ = { graph_.vertexEdgeIncidences_[incidence_].vertex, incidence_ >> 1 };
}
}
};
NeighborIterator begin(const int vertex) const;
NeighborIterator end() const;
private:
std::vector<int> firstVertexIncidences_;
std::vector<VertexEdgeIncidence> vertexEdgeIncidences_;
std::vector<int> edgeWeights_;
std::vector<int> vertexWeights_;
};