标签:
代码如下:
void floyd_warshall(const vector<vector<double>>& edge_weights,vector<vector<double>>& smallest_length,vector<vector<int>>& pred)
{
const int NIL=-1; //NIL表示不存在的顶点;
const int vertex_number=edge_weights.size();
//从顶点i到顶点j没有经过其它顶点时的smallest_length,所以此时为边的权重edge_weights;
//pred表示此时对应的最短路径
for(int i=0;i!=vertex_number;++i)
for(int j=0;j!=vertex_number;++j)
{
if(i==j||edge_weights[i][j]==DBL_MAX)
pred[i][j]=NIL;
else
pred[i][j]=i;
smallest_length[i][j]=edge_weights[i][j];
}
vector<vector<double>> L(vertex_number);
vector<vector<double>> p(vertex_number);
for(int i=0;i!=vertex_number;++i)
{
L[i].resize(vertex_number);
p[i].resize(vertex_number);
}
for(int k=0;k!=vertex_number;++k)
{
//矩阵L表示中间顶点来自集合[0..k]时的顶点i到顶点j的最短路径权重和,矩阵p表示对应的路径;
//smallest_length表示中间顶点来自集合[0..k-1]时的顶点i到顶点j的最短路径权重和,矩阵pred表示对应的路径。
for(int i=0;i!=vertex_number;++i)
for(int j=0;j!=vertex_number;++j)
if(smallest_length[i][k]!=DBL_MAX&&smallest_length[k][j]!=DBL_MAX){
if(smallest_length[i][j]<=smallest_length[i][k]+smallest_length[k][j]){
p[i][j]=pred[i][j];
L[i][j]=smallest_length[i][j];
}
else{
p[i][j]=pred[k][j];
L[i][j]=smallest_length[i][k]+smallest_length[k][j];
}
}
else{
L[i][j]=smallest_length[i][j];
p[i][j]=pred[i][j];
}
//把矩阵L和p分别赋值给smallest_length和pred,使得smallest_length此时
//表示中间顶点来自集合[0..k]时的顶点i到顶点j的最短路径权重和,矩阵pred表示对应的路径
for(int i=0;i!=vertex_number;++i)
for(int j=0;j!=vertex_number;++j)
{
smallest_length[i][j]=L[i][j];
pred[i][j]=p[i][j];
}
}
}
代码如下:
vector<vector<double>> transitive_closure(const vector<list<int>>& graph,
const vector<vector<double>>& edge_weights)
{
const int vertex_number=graph.size();
vector<vector<double>> t(vertex_number);
vector<vector<double>> tmp(vertex_number);
for(int i=0;i!=t.size();++i)
{
t[i].resize(vertex_number);
tmp[i].resize(vertex_number);
}
for(int i=0;i!=vertex_number;++i)
for(int j=0;j!=vertex_number;++j)
if(i==j||edge_weights[i][j]!=DBL_MAX)
t[i][j]=1;
else
t[i][j]=0;
for(int k=0;k!=vertex_number;++k)
{
for(int i=0;i!=vertex_number;++i)
for(int j=0;j!=vertex_number;++j)
tmp[i][j]=t[i][j]||(t[i][k]&&t[k][j]);
for(int i=0;i!=vertex_number;++i)
for(int j=0;j!=vertex_number;++j)
t[i][j]=tmp[i][j];
}
return t;
}
1. 对于所有节点对(u,v),一条路径p是在使用原先权重函数时从结点u到结点v的一条最短路径,当且仅当p是在使用新权重函数时从u到v的一条最短路径;
2. 对于所有的边(u,v),新权重为非负值。
具体的操作过程见25.3节。代码如下:
//在已有图(假设有k个顶点)的基础上增加一个新的顶点,假设该新顶点的标号为k+1;
void add_source(vector<list<int>>& graph,vector<vector<double>>& edge_weights,vector<edge>& graph_edge)
{
//链表adjacent_vertex中存储的是与新顶点相邻的顶点,新顶点与原先顶点全部相邻,但原先顶点不与新顶点相邻;
const int new_vertex_label=graph.size();
list<int> adjacent_vertex;
for(int i=0;i!=graph.size();++i){
adjacent_vertex.push_back(i);
graph_edge.push_back(edge(new_vertex_label,i));
}
graph.push_back(adjacent_vertex);
for(int i=0;i!=edge_weights.size();++i)
edge_weights[i].push_back(DBL_MAX); //原先图中顶点与新顶点不相邻;
//新增加的顶点与相邻顶点的边的权重值为0,
//这时候graph.size()已经包括了新增的顶点;
vector<double> new_edges_weights(graph.size(),0);
edge_weights.push_back(new_edges_weights);
}
void Johnson(vector<list<int>>& graph,vector<vector<double>>& edge_weights,vector<edge>& graph_edge,
vector<vector<double>>& smallest_length,vector<vector<int>>& pred)
{
add_source(graph,edge_weights,graph_edge);
const int new_vertex_label=graph.size()-1;
//矢量smallest_weights存储的的是图中顶点到新增加顶点的最短路径权重,
//矢量p存储的是对应的各个顶点的前驱结点;
vector<double> smallest_weights(graph.size());
vector<int> p(graph.size());
if(bellman_ford(new_vertex_label,graph,edge_weights,graph_edge,smallest_weights,p)==false){
cout<<"The input graph contains a negative-weight cycle"<<endl;
return;
}
vector<double> h;
for(int i=0;i!=smallest_weights.size();++i)
h.push_back(smallest_weights[i]);
for(int u=0;u!=edge_weights.size();++u)
for(int v=0;v!=edge_weights[u].size();++v)
if(edge_weights[u][v]!=DBL_MAX)
edge_weights[u][v]+=h[u]-h[v]; //确保图中各个边的权重大于0,以便调用Dijkstra算法。
//矩阵smallest_length存储的是原先图中结点对之间的最短路径权重;
//矩阵pred存储的是对应路径中各个顶点的前驱结点。
for(int u=0;u!=new_vertex_label;++u)
{
Dijkstra(u,graph,edge_weights,smallest_weights,p);
for(int i=0;i!=new_vertex_label;++i)
{
smallest_length[u][i]=smallest_weights[i];
pred[u][i]=p[i];
}
for(int v=0;v!=new_vertex_label;++v)
smallest_length[u][v]+=h[v]-h[u];
}
}
第25章:所有结点对的最短路径问题—floyd-warshall和Johnson算法
标签:
原文地址:http://blog.csdn.net/weishenmetlc/article/details/51920423