bellman-find算法与dijkstra算法有一点相似,不过我们在这个算法中维护了一个队列来进行下一步的遍历。但是bellman-find算法也有一个局限,便是不呢处理具有负权重环的图。
/*bellman - find算法*/
class bellman_find
{
private:
double *dist_to; //路径长度
std::vector<diedge> edge_to;
bool *onq;
std::queue<int> q;
int cost;
std::vector<diedge> cycle;
void find_necycle()
{
int v = edge_to.size();
EWdigraph spt(v);
for (int i = 0; i < v; i++)
{
if (edge_to[i].weight() != inf)
{
spt.add_edge(edge_to[i]);
}
}
/*缺少类*/
}
void relax(EWdigraph g, int v)
{
for (diedge e : g.iterator(v))
{
int w = e.to();
if (dist_to[w] > dist_to[v] + e.weight())
{
dist_to[w] = dist_to[v] + e.weight();
edge_to[w] = e;
if (!onq[w])
{
q.push(w);
onq[w] = true;
}
if (cost++%g.numv() == 0)
{
find_necycle();
}
}
}
}
public:
bool has_necycle()
{
return !cycle.empty();
}
bellman_find(EWdigraph g, int s)
{
dist_to = new double[g.numv()];
edge_to.resize(g.numv());
onq = new bool[g.numv()];
std::fill(dist_to, dist_to + g.numv(), inf);
std::fill(onq, onq + g.numv(), 0);
dist_to[s] = 0;
q.push(s);
onq[s] = true;
while (!q.empty()&&!has_necycle())
{
int v = q.front();
q.pop();
onq[v] = false;
relax(g, v);
}
}
double dist(int to)
{
return dist_to[to];
}
};
运行结果
老规矩,你可以看到我留下了一个edge_to的vector容器,你可以增加返回路径或者其他数据的方法。此外,由于该算法只能判断无负权重环的加权有向有向图的最短路径,所以本应该有一个判断是否有负权重环的方法。由于书中调用了一个判断是否有负权重环的方法,却并没有给出相应的实现;加之并非必要,所以我在此并没有实现那个方法,而是进行了留白。感兴趣的朋友可以参考拓扑排序中寻找有向环的方法对这个类进行构造