Given a weighted digraph with weights either 0 or 1 find the shortest path. I heard that it can be solved using BFS and deque. But I don't really know how to prevent an vertex from appearing in the deque several times. Which condition on adding them to deque should I add? Thanks.
First of all you can use queue for bfs, not deque.
Try to use bool array was[] for all vertexes.
was[x] == 1
— you've already added a vertex x to queue. And you should add a vertex to queue only ifwas[x] != 1
UPD: Sorry, I didn't notice 0,1 weights. In this case you should add a vertex only if shortest distance to it has changed. Or use was[] array and if you've got to vertex by an edge with 0 weight — add it to head of deque else tail.
Just store the distance from the source:
First, initialize to infinity all the distances:
Then, initialize to zero the distance from the source:
So, whenever you have to decide whether to add or not a neighboring node to the deque, you will first check if the distance found so far for that node is worse than the one you are proposing now:
If that conditions evaluates to true, you will add that node to the deque (to the front if edge_weight is 0, to the back if it is 1) AND you will update the distance to that node with the value you proposed.
but according to your code it seems to me that one vertex can still appear in your deque several times :-)
UPD: can you prove to me please that one vertex won't appear in the deque twice?
Yes, a node can appear twice:
The deque operations:
I think you shouldn't worry too much about it, because the second time you pop a node from the deque the "if" condition on its neighbors will always fail, and you will drop that node. If you are really worried, you can change the
deque<int>
to adeque< pair<int,int> >
so you can store the distance of the node: in this way the previous deque operations become:Having this information, you can decide whether to drop or not the node right after popping it from the deque:
This way you can avoid looking all the neighbors before dropping the node.
When you do a normal BFS only with 1-weight edges note that nodes are always inserted into the queue sorted by distance, so every time you pop a node it will be one of the "closest". When you have 0-weight and 1-weight edges you should insert nodes also sorted by distance. Suppose you have popped a node U with distance D, then you try to insert its adjacent nodes, note that an adjacent node of U with 0-weight will have the same distance D of U, so it should be "processed" (popped) before any other nodes with distance D + 1. To ensure that you push it in the front of the deque, so the next node you pop will be one with distance D (because you pop nodes from the front). Adjacent nodes with 1-weight edges should be pushed in the back of the deque as in a normal BFS. Pushing nodes in the front or back, you guaranteed that all nodes with distance D are processed before nodes with distance D + 1. So each node will be pushed and popped at most once, so it is O(V + E).
step1: Try to go through 0-edges only. when you can't anymore go to step2
step2: visit only one node using 1-edge and back to step1
stop when you visit all nodes or you can't anymore visit a new node(in case of not connected graph)
I think it's important which node in step 2 you choose and it is not that easy to chose it, so you can't just state: "visit one node using 1-edge", because it doesn't always bring you to the right answer. You just don't know what edges come next and if you start checking that the solution can become really slow
ok, you choose the 1-edge such that you are going from a node which the number of 1-egdes used to come to this node is minimal