我正在研究一个问题,我需要找到给定的定向未加权图中两个节点之间的所有最短路径。我已经使用BFS算法来完成这项工作,但不幸的是我只能打印一条最短的路径而不是所有的路径,例如,如果它们是长度为3的4条路径,我的算法只打印第一条但我希望它能打印所有四条最短路径。我想知道下面的代码,我应该如何更改它,以便打印出两个节点之间的所有最短路径?
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
}
我非常感谢你的帮助 谢谢, 的Andra
答案 0 :(得分:2)
map<int, map<int,graphNode>* > graph
声明每个边缘有一个graphNode
个对象的图表。
每个节点一个graphNode
的类型为map<int, map<int,graphNode*> >
,或者更好,map<graphNode*, set /* or vector */<graphNode*> >
,或者更好,multimap< graphNode *, graphNode * >
。
graphNode
需要存储在您使用的vector
内的单独结构中(例如deque
或map
)。
int parents[graph.size()+1];
是非标准的。请改用vector<int> parents( graph.size()+1 );
。
要回答您的问题,您希望继续使用BFS,直到达到拓扑顺序大于第一个结果的第一个节点。引入变量int first_id_of_next_level = v.id;
。 (或者更好的是,使用指针。)找到匹配项后,将其路径追加到路径列表中。当gn == first_id_of_next_level
,return
列表(如果不是empty
或设置first_id_of_next_level = p->first
),当前父级的第一个孩子时,您知道下次停止搜索的机会
答案 1 :(得分:1)
要编写所有最短路径,您必须编写类似递归DFS的算法。运行BFS以查找到每个节点的最小距离,将其存储,然后从源节点运行DFS,仅分支到满足最小路径的节点。每当到达目标节点时,请写下您到达目的地的路径(您在递归函数中一直在跟踪)。请注意,您不会在DFS中标记节点。
由于算法需要回溯,因此最好的方法是通过递归DFS。你可以用BFS编写它,但你必须维护一个堆栈来跟踪你的回溯,这意味着你实际上是用手动维护的堆栈编写DFS,即编写完全相同的算法代码是您需要的代码的两倍。
请注意,最短路径的数量并不总是多项式,因此您可能正在编写指数路径。