我们经常用dijkstra算法来计算最短路径,其原理可以参考http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm.
boost库也提供了它的实现,我们就以上图为准,利用boost库中dijkstra算法对其做一个简单的实现:
#include <iostream>
#include<boost\graph\adjacency_list.hpp>
#include<boost\graph\dijkstra_shortest_paths.hpp>
typedef boost::adjacency_list < boost::listS, boost::vecS, boost::directedS, boost::no_property, boost::property < boost::edge_weight_t, unsigned long > > graph_t;
typedef boost::graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits < graph_t >::edge_descriptor edge_descriptor;
#include<vector>
using namespace std;
//Node定义
struct Node
{
int nId; //Node编号
};
//Link定义
struct Link
{
int nStartNodeId; //起始Node编号
int nEndNodeId; //终止Node编号
int nLength; //Link的长度
Link(int nSId,int nEId,int nLen)
{
nStartNodeId=nSId;
nEndNodeId=nEId;
nLength=nLen;
}
};
//获取路径经过结点的信息
void GetPath(int fromId,int toId,vector<vertex_descriptor>& vPredecessor,std::string& strPath)
{
vector<int> vecPath;
while(fromId!=toId)
{
vecPath.push_back(toId);
//因为本例子的特殊性和自己很懒,所以可以直接取值
toId = vPredecessor[toId];
}
vecPath.push_back(toId);
vector<int>::reverse_iterator pIter = vecPath.rbegin();
strPath="路径:";
std::string strOperator="->";
char c[20]={};
for(;pIter!=vecPath.rend();pIter++)
{
itoa(*pIter,c,10);
if(*pIter!=fromId)
{
strPath+=(strOperator+c);
}
else
{
strPath+=c;
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
//构造Node集合
vector<Node> vecNodes;
for(int i=1;i<=6;i++)
{
Node nd;
nd.nId = i;
vecNodes.push_back(nd);
}
//构造Link集合
vector<Link> vecLinks;
Link lk(1,3,9);
vecLinks.push_back(lk);
Link lk1(1,2,7);
vecLinks.push_back(lk1);
Link lk2(1,6,14);
vecLinks.push_back(lk2);
Link lk3(2,4,15);
vecLinks.push_back(lk3);
Link lk4(2,3,10);
vecLinks.push_back(lk4);
Link lk5(3,4,11);
vecLinks.push_back(lk5);
Link lk6(3,6,2);
vecLinks.push_back(lk6);
Link lk7(6,5,9);
vecLinks.push_back(lk7);
Link lk8(4,5,6);
vecLinks.push_back(lk8);
//图定义
graph_t g;
g.clear();
boost::property_map<graph_t, boost::edge_weight_t>::type pmpWeightmap = boost::get(boost::edge_weight, g);
for(int i=0;i<vecLinks.size();i++)
{
edge_descriptor edEdge;
bool bInserted;
//加入Link的起始和终止NodeID
boost::tie(edEdge,bInserted)=boost::add_edge(vecLinks[i].nStartNodeId,vecLinks[i].nEndNodeId,g);
//加入Link的长度
pmpWeightmap[edEdge]=vecLinks[i].nLength;
}
//路径计算结果定义
vector<vertex_descriptor> vPredecessor(boost::num_vertices(g)); //存储从起始结点到其他结点的路径上经过的最后一个中间结点序号
vector<unsigned long> vDistance(boost::num_vertices(g)); //存储起始结点到其他结点的路径的距离
//路径探索起始点定义
vertex_descriptor s = boost::vertex(vecNodes[0].nId, g);
//路径计算
boost::property_map<graph_t, boost::vertex_index_t>::type pmpIndexmap = boost::get(boost::vertex_index, g);
boost::dijkstra_shortest_paths(g, s, &vPredecessor[0], &vDistance[0], pmpWeightmap, pmpIndexmap,
std::less<unsigned long>(), boost::closed_plus<unsigned long>(),
std::numeric_limits<unsigned long>::max(), 0, boost::default_dijkstra_visitor());
std::string strPath;
GetPath(1,5,vPredecessor,strPath);
cout<<strPath<<endl;
cout<<"路径长度:"<<vDistance[5]<<endl;
return 0;
}