C++ 用BFS算法求无权有向图中两节点间的所有最短路径
我正在研究一个问题,我需要在给定的有向无权图中找到两个节点之间的所有最短路径。我使用BFS算法来完成这项工作,但不幸的是,我只能打印一条最短路径,而不是所有路径,例如,如果它们是长度为3的4条路径,我的算法只打印第一条路径,但我希望它打印所有四条最短路径。在下面的代码中,我想知道应该如何更改它,以便打印出两个节点之间的所有最短路径C++ 用BFS算法求无权有向图中两节点间的所有最短路径,c++,breadth-first-search,shortest,C++,Breadth First Search,Shortest,我正在研究一个问题,我需要在给定的有向无权图中找到两个节点之间的所有最短路径。我使用BFS算法来完成这项工作,但不幸的是,我只能打印一条最短路径,而不是所有路径,例如,如果它们是长度为3的4条路径,我的算法只打印第一条路径,但我希望它打印所有四条最短路径。在下面的代码中,我想知道应该如何更改它,以便打印出两个节点之间的所有最短路径 class graphNode{ public: int id; string name; bool stat
class graphNode{
public:
int id;
string name;
bool status;
double weight;
};
map<int, map<int,graphNode>* > graph;
int Graph::BFS(graphNode &v, graphNode &w){
queue <int> q;
map <int, int> map1; // this is to check if the node has been visited or not.
std::string str= "";
map<int,int> inQ; // just to check that we do not insert the same iterm twice in the queue
map <int, map<int, graphNode>* >::iterator pos;
pos = graph.find(v.id);
if(pos == graph.end()) {
cout << v.id << " does not exists in the graph " <<endl;
return 1;
}
int parents[graph.size()+1]; // this vector keeps track of the parents for the node
parents[v.id] = -1;
if (findDirectEdge(v.id,w.id) == 1 ){
cout << " Shortest Path: " << v.id << " -> " << w.id << endl;
return 1;
} //if
else{
int gn;
map <int, map<int, graphNode>* >::iterator pos;
q.push(v.id);
inQ.insert(make_pair(v.id, v.id));
while (!q.empty()){
gn = q.front();
q.pop();
map<int, int>::iterator it;
cout << " Popping: " << gn <<endl;
map1.insert(make_pair(gn,gn));
if (gn == w.id){//backtracing to print all the nodes if gn is the same as our target node such as w.id
int current = w.id;
cout << current << " - > ";
while (current!=v.id){
current = parents[current];
cout << current << " -> ";
}
cout <<endl;
}
if ((pos = graph.find(gn)) == graph.end()) {
cout << " pos is empty " <<endl;
continue;
}
map<int, graphNode>* pn = pos->second;
map<int, graphNode>::iterator p = pn->begin();
while(p != pn->end()) {
map<int, int>::iterator it;
it = map1.find(p->first);//map1 keeps track of the visited nodes
graphNode gn1= p->second;
if (it== map1.end()) {
map<int, int>::iterator it1;
it1 = inQ.find(p->first); //if the node already exits in the inQ, we do not insert it twice
if (it1== inQ.end()){
parents[p->first] = gn;
cout << " inserting " << p->first << " into the queue " <<endl;
q.push(p->first); // add it to the queue
} //if
} //if
p++;
} //while
} //while
}
类图形节点{
公众:
int-id;
字符串名;
布尔状态;
双倍重量;
};
地图图;
int-Graph::BFS(graphNode&v、graphNode&w){
队列q;
map map1;//检查节点是否已被访问。
std::string str=“”;
map inQ;//只是为了检查我们没有在队列中插入相同的iterm两次
迭代器位置;
pos=图形查找(v.id);
if(pos==graph.end()){
库特
map-graph
声明一个每边有一个graphNode
对象的图
每个节点的一个graphNode
将具有类型map
,或者更好的是,map
,或者更好的是,multimap
graphNode
s需要从您使用的map
存储在单独的结构中(例如,vector
或deque
)
int父项[graph.size()+1];
是非标准的。请改用向量父项(graph.size()+1);
要回答您的问题,您需要继续BFS,直到到达拓扑顺序大于第一个结果的第一个节点。请引入变量int first\u id\u of_next\u level=v.id;
(或者更好,使用指针)找到匹配项后,将其路径附加到路径列表中。当gn==first\u id\u of_next\u level
时,如果列表不是empty
则返回该列表,或者设置first\u id\u of_next\u level=p->first
,即当前父级的第一个子级,这样您就知道下一次停止搜索的机会
要编写所有最短路径,您必须编写一个类似DFS的递归算法。运行BFS以查找到每个节点的最小距离,存储该距离,然后从源节点运行DFS,仅分支到满足最小路径的节点。每当到达目标节点时,请编写到达目标节点的路径(您一直在递归函数中跟踪它)。请注意,您不会在DFS中标记节点
由于该算法需要回溯,因此最好的方法是通过递归DFS。您可以使用BFS编写该算法,但您必须维护堆栈以跟踪回溯,这意味着您实际上是使用手动维护的堆栈编写DFS,即使用两倍于您需要的代码编写完全相同的算法对
请注意,最短路径的数量并不总是多项式的,因此您可能正在编写指数数量的路径。您的算法是正确的,但措词不正确,很容易与拓扑排序混淆,拓扑排序与最短路径无关。存在O(E)算法而不是指数1@bitec不,没有。怎么可能有一个线性算法来写指数数量的项目?说话之前先想一想。对不起,我错了。我的意思是使用编辑过的BFS的算法需要O(E)准备路径,然后可以按指数方式打印它们。但我的意思是,在找到最小距离(M)后的变体中,您建议使用修改的DFS来查找所有路径(不将节点标记为永久访问,但仅在递归循环中)当路径超过M时,完成递归。这可能导致指数工作,即使只有几个最短路径。这就是我的意思