#include <iostream>
#include <map>
#include <vector>
#include <stdexcept>
#include <memory>
namespace{
enum : int{
MAXVALUE = 9999;
};
}
template<typename T>
class Node{
public:
T key_;
template<typename Ty>
Node(const T& key);
Node()=default;
Node(const Node<T>& otherNode_);
template<typename Ty>
Node(Node<Ty>&& otherNode_);
template<typename Ty>
Node(Node<Ty>* node_ptr_);
const Node<T>& operator=(const Node<T>& otherNode_);
template<typename Ty>
const Node<Ty>& operator=(Node<Ty>&& otherNode_);
template<typename Ty>
friend bool operator<(const Node<Ty>& first_, const Node<Ty>& second_);
template<typename Ty>
friend bool operator==(const Node<Ty>& first_, const Node<Ty>& second_);
~Node()=default;
using node_type = T;
};
template<typename T>
template<typename Ty>
Node<T>::Node(const Ty& key)
:key_(key)
{
//default constructor.
}
template<typename T>
Node<T>::Node(const Node<T>& otherNode_)
:key_(otherNode_.key_)
{
//copy-constructor.
}
template<typename T>
template<typename Ty>
Node<T>::Node(Node<Ty>&& otherNode_)
:key_(otherNode_.key_)
{
//move-constructor.
}
template<typename T>
template<typename Ty>
Node<T>::Node(const Node<Ty>* node_ptr_)
:key_(node_ptr_.key_)
{
//
}
template<typename T>
const Node<T>& Node<T>::operator=(const Node<T>& otherNode_)
{
this->key_ = otherNode_.key_;
return *this;
}
template<typename T>
template<typename Ty>
const Node<Ty>& Node<T>::operator=(Node<Ty>&& otherNode_)
{
this->key_ = otherNode_.key_;
return *this;
}
template<typename Ty>
bool operator<(const Node<Ty>& first_, const Node<Ty>& second_)
{
return (first_.key_ < second_.key_) ? true : false;
}
template<typename Ty>
bool operator==(const Node<Ty>& first_, const Node<Ty>& second_)
{
return (first_.key_ == second_.key_) ? true : false;
}
template<typename T>
class Graph{
private:
std::map<Node<T>, std::map<Node<T>, int>> graph_; //存储有向图.在下面的构造函数中会把新结点(默认为0)加入进去。
std::map<Node<T>, int> distance_; //保存从给定顶点到各个顶点所经过的路程.
std::map<Node<T>, std::vector<Node<T>>> adjList_;
std::map<Node<T>, bool> whether_visited_; //用于dijstra算法. 判断当前结点是否被访问过,默认都为false.
std::vector<Node<T>> have_find_; //用于dijstra算法. 存放已经找到最短路径的结点.
std::map<Node<T>, Node<T>> node_to_node_;
std::map<Node<T>, std::vector<Edge<T>>> one_for_all_; //当Node<T>作为源结点的时候,对应的有向图中源结点到各个结点的距离.
unsigned int node_number_;
T source_key_;
bool flag_; //如果给定的有向图中存在负环路,那么flag_为true,否则为false.(默认为false).
template<typename Ty>
void bellman_ford(const Ty& source_data); //之所以使用Bellman-ford算法是因为该算法允许存在权重为负数的边.
void initialize_single_source()noexcept;
template<typename Ty>
void relax(const Node<Ty>& first_, const Node<Ty>& second_)noexcept;
template<typename Ty>
void dijstra_algorithm(const Node<Ty>& node_)noexcept;
template<typename Ty>
void initialized_distance(const Node<Ty>& source_)noexcept;
template<typename Ty>
void relax_dijstra(const Node<Ty>& first_, const Node<Ty>& second_)noexcept;
void transition()noexcept; //这是一个过渡函数用于bellman-ford算法结束后和Dijstra算法开始前.
//其主要用于在bellman-ford算法执行结束后求得给定的源节点(source)到图中各个结点间的最短路径后把这些路径更新到graph_中.
template<typename Ty>
void helper_function(const Node<Ty>& node_)noexcept;
template<typename edge_type>
class Edge{
public:
std::shared_ptr<Node<edge_type>> start_;
std::shared_ptr<Node<edge_type>> end_;
int weighting_; //该边的加权值.
Edge()=default;
template<typename Ty>
Edge(const Ty& start, const Ty& end_);
template<typename Ty>
Edge(const Node<Ty>& first_, const Node<Ty>& second_);
Edge(cosnt Edge<T>& otherEdge_);
template<typename Ty>
Edge(Edge<Ty>&& otherEdge_);
const Edge<edge_type>& operator=(const Edge<edge_type>& otherEdge_);
template<typename Ty>
const Edge<Ty>& operator=(Edge<Ty>&& otherEdge_);
~Edge()=default;
};
public:
using map_iter = typename std::map<Node<T>, int>::const_iterator;
using map_in_map_iter = typename std::map<Node<T>, std::map<Node<T>, int>>::const_iterator;
using vec_iter = typename std::vector<Node<T>>::const_iterator;
using mapVec_iter = typename std::map<Node<T>, std::vector<Node<T>>>::const_iterator;
template<typename Ty, unsigned int N>
Graph(const Ty (&edges)[N][3]);
Graph()=default;
template<typename Ty>
void johnson_algorithm(const Ty& source_);
~Graph();
};
template<typename T>
template<typename edge_type>
template<typename Ty>
Graph<T>::Edge<edge_type>::Edge(const Ty& start, const Ty& end)
:Edge(Node<Ty>(start), Node<Ty>(end))
{
//the constructor of edge;
}
template<typename T>
template<typename edge_type>
template<typename Ty>
Graph<T>::Edge<edge_type>::Edge(const Node<Ty>& first_, const Node<Ty>& second_)
:start_(std::make_shared<Node<Ty>>(Node<Ty>(first_))),
end_(std::make_shared<Node<Ty>>(Node<Ty>(second_)))
{
//
}
template<typename T>
template<typename edge_type>
Graph<T>::Edge<edge_type>::Edge(const Edge<edge_type>& otherEdge_)
:start_(otherEdge_.start_),
end_(otherEdge_.end_),
weighting_(0)
{
//copy-constructor for edge;
}
template<typename T>
template<typename edge_type>
template<typename Ty>
Graph<T>::Edge<edge_type>::Edge(Edge<Ty>&& otherEdge_)
:start_(otherEdge_.start_),
end_(otherEdge_.end_),
weighting_(otherEdge_.weighting_)
{
otherEdge_.start_.reset();
otherEdge.end_.reset();
//move-constructor for edge;
}
template<typename T>
template<typename edge_type>
const Edge<edge_type>& Graph<T>::Edge<edge_type>::operator=(const Edge<edge_type>& otherEdge_)
{
this->start_ = otherEdge_.start_;
this->end_ = otherEdge_.end_;
this->weighting_ = otherEdge_.weighting_;
return *this;
//operator=;
}
template<typename T>
template<typename edge_type>
template<typename Ty>
const Edge<Ty>& Graph<T>::Edge<edge_type>::operator=(Edge<Ty>&& otherEdge_)
{
this->start_ = otherEdge_.start_;
this->end_ = otherEdge_.end_;
this->weighting_ = otherEdge_.weighting_;
otherEdge_.start_.reset();
otherEdge_.end_.reset();
return *this;
}
template<typename T>
template<typename Ty, unsigned int N>
Graph<T>::Graph(const Ty (&edges)[N][3])
:node_number_(N),//注意这里的node_number_ = N;
flag_(false)
{
if(N == 0){
throw std::runtime_error(std::string("there is nothing in graph"));
}
Node<Ty> temp_node(0); //temp_node作为我们新加入的结点.
//存储有向图.
//同时新建一个结点(temp_node)该结点与图中其他结点的之间的加权值为0.
for(int i=0; i<N; ++i){
Node<Ty> first_(edges[i][0]);
Node<Ty> second_(edges[i][1]);
for(int j=0; j<N; ++j){
Node<Ty> third_(edges[i][0]);
if(first_ == third_){
this->graph_[first_][third_] = 0;
continue;
}
this->graph_[first_][third_] = ::MAXVALUE;
}
this->graph_[first_][second_] = edges[i][2];
this->graph_[temp_node][first_] = 0;
this->graph_[temp_node][second_] = 0;
this->distance_.insert(std::pair<Node<Ty>, int>(first_, ::MAXVALUE));
this->distance_.insert(std::pair<Node<Ty>, int>(second_, ::MAXVALUE));
this->adjList_[first_].push_back(second_); //每个结点的邻接链表.
this->whether_visited_[first_] = false;
this->whether_visited_[second_] = false;
}
this->whether_visited_[temp_node] = false;
this->distance_.insert(std::pair<Node<Ty>, int>(temp_node, 0));
std::cout<<"construct a graph successfully!"<<std::endl;
}
template<typename Ty>
void Graph<T>::initialize_single_source()noexcept
{
Node<T> source_node(this->source_key_);
this->distance_[source_node] = 0; //把源结点距离自己的距离初始化为0.
}
template<typename T>
template<typename Ty>
void Graph<T>::bellman_ford(const Ty& source_data) //通过Bellman-ford算法求出 新加入的结点到各个结点的最短距离.
{
this->source_key_ = source_data;
this->initialize_single_source();
for(int 1=0; i<this->node_number_; ++i){ //注意这里的node_number_是N(N代表原图中结点的个数我们新加入的那个结点的是没有被算进去的).
mapVec_iter iter_first_ = this->adjList_.cbegin();
for(; iter_first_ != this->adjList_.cend(); ++iter_first_){
vec_iter iter_second_ = this->adjList_[iter_first_->first].cbegin();
for(; iter_second_ != this->adjList_[iter_first_->first].cend(); ++iter_second_){
this->relax(iter_first_->first, *iter_second);
}
}
}
mapVec_iter iter_third_ = this->adjList_.cbegin();
for(; iter_third_ != this->adjList_.cend(); ++iter_third_){ //判断是否存在负环路.
vec_iter iter_forth_ = this->adjList_[iter_third_->first].cbegin();
for(; iter_forth_ != this->adjList_[iter_third_->first].cend(); ++iter_forth_){
if(this->distance_[*iter_forth_] > this->distance_[*iter_third_] + this->graph_[iter_third_->first][*iter_forth]){
this->flag_ = true; //设为true表明存在负回路.
break;
}
}
if(this->flag_){
break;
}
}
}
template<typename T>
template<typename Ty>
void Graph<T>::relax(const Node<Ty>& first_, const Node<Ty>& second_)
{
if(this->distance_[second_] > this->distance_[first_] + this->graph_[first_][second_]){
this->distance_[second_] = this->distance_[first_] + this->graph_[first_][second_];
}
}
template<typename T>
void Graph<T>::transition()noexcept
{
Node<T> source_node(this->source_key_);
map_iter iter = this->distance_.cbegin();
for(; iter != this->distance_.cend(); ++iter){
this->graph_[source_node][iter->first] = this->distance_[iter->first];
}
}
template<typename T>
template<typename Ty>
void Graph<T>::dijstra_algorithm(const Node<Ty>& node_)noexcept
{
//注意这个+1,因为node_number_在初始化的时候被赋值为N.(N是不包含给定的源结点的,源结点是我们自己给出的不同于图中任何一个结点).
for(int i=1; i<this->node_number_+1; ++i){
Node<T> temp_node = node_;
int temp_weighting = ::MAXVALUE;
vec_iter iter_ = this->adjList_[source_node].cbegin();
for(; iter_ != this->adjList_[source_node].cend(); ++iter_){
if(this->whether_visited_[*iter_] == false && this->graph_[source_node][*iter_] < temp_weighting){
temp_weighting = this->graph_[source_node][*iter_];
temp_node = *iter_;
}
}
this->whether_visited_[source_node] = true; //已经访问过的结点被设置为true.
mapVec_iter iter_first_ = this->adjList_.cbegin();
for(; iter_first_ != this->adjList_cend(); ++iter_first_){
this->relax_dijstra(iter_first->first, temp_node);
}
}
}
template<typename T>
template<typename Ty>
void Graph<T>::relax_dijstra(const Node<Ty>& first_, const Node<Ty>& second_) //second----first想象成一条边.
{
if(this->whether_visited_[first_] == false && this->graph_[second_][first_] < ::MAXVALUE){
if(this->distance_[second_] + this->graph_[second_][first_] < this->distance_[first_]){
this->distance_[first_] = this->distance_[second_] + this->graph_[second_][first_];
this->node_to_node_[first_] = second_; //first结点的前驱结点为second_;
}
}
}
template<typename T>
template<typename Ty>
void Graph<T>::johnson_algorithm(const Ty& source_)
{
this->bellman_ford(0);
if(this->flag_){
throw std::runtime_error(std::string("There is negative-cycle in graph.\n"));
}
this->transiton(); //过渡函数.
mapVec_iter iter_first_ = this->adjList_.cbegin();
for(; iter_first_ != this->adjList_.cend(); ++iter_first_){
this->dijstra_algorithm(iter_first_->first);
this->helper_function(iter_first_->first);
}
}
template<typename T>
template<typename Ty>
void Graph<T>::helper_function(const Node<Ty>& node_)noexcept
{
map_iter iter_first = this->distance_.cbegin();
for(; iter_first != this->distance_.cend(); ++iter_first){
Edge<Ty> temp_edge(node_, iter_first->first);
temp_edge.weighting = iter_first->second;
this->one_to_all_[node_].push_back(temp_edge);
}
}