Mari menjadi grafik, dan biarkan dan dua simpul dari . Bisakah kita secara efisien mencicipi terpendek - secara seragam dan independen secara acak dari rangkaian semua jalur terpendek antara dan ? Untuk kesederhanaan, kita dapat menganggap sederhana, tidak terarah dan tidak berbobot.
Bahkan di banyak grafik terbatas, jumlah jalur terpendek antara dan dapat eksponensial dalam ukuran . Oleh karena itu, kita tentu ingin menghindari sebenarnya menghitung semua jalur - terpendek . Saya tidak tahu tentang kasus umum, tetapi bagi saya tampaknya kita dapat mencapai ini untuk beberapa kelas grafik khusus.
Ini terasa seperti sesuatu yang seseorang harus pertimbangkan sebelumnya. Apakah ada penelitian yang ada tentang ini, atau apakah ini sebenarnya mudah dilakukan bahkan untuk grafik umum?
Jawaban:
Saya tidak 100% yakin jawaban ini benar, tetapi begini:
Saya pikir Anda dapat mengurangi ini untuk acak sembarang-jalur, dari , dalam DAG dengan satu sumber dan satu wastafel.s−t
Diberikan grafikG
Essentially, I am collecting all possible nodes that can be used in the shortest-path, and placing them inH .
More on how this works:
Now we have a DAG that we can traverse in any way fromt−s , and obtain a shortest-reversed-path from s−t . The graph should have t as the only source, and s as the only sink.
If the above is correct, then I think we can take this a step further and solve the problem as follows.
Give each node in the DAG a node-weight; the node-weight will be the number of paths from from that node tos . Let us call this w(v) .
You can compute these quickly, see Algorithm that finds the number of simple paths from s to t in G.
Once we have the node-weight, we can uniformly pick a path by:
Layout the DAG as a level-structure (for visualization)At each level, choose an arbitrary ordering between the nodes ie. a notion of "left to right".sumber
Here is a solution based upon the ideas in Realz Slaw's answer. It is basically a re-exposition of his ideas that might be clearer or easier to follow. The plan is that we will proceed in two steps:
First, we will build a graphS with the following property: any path from s to t in S is a shortest path from s to t in G , and every shortest path from s to t in G is also present in S . Thus, S contains exactly the shortest paths in G : all the shortest paths, and nothing more. As it happens, S will be a DAG.
Next, we will sample uniformly at random from all paths froms to t in S .
This approaches generalizes to an arbitrary directed graphG , as long as all edges have positive weight, so I'll explain my algorithm in those terms. Let w(u,v) denote the weight on the edge u→v . (This generalizes the problem statement you gave. If you have an unweighted graph, just assume every edge has weight 1. If you have an undirected graph, treat each undirected edge (u,v) as the two directed edges u→v and v→u .)
Step 1: extractS . Run a single-source shortest-paths algorithm (e.g., Dijkstra's algorithm) on G , starting from source s . For each vertex v in G , let d(s,v) denote the distance from s to v .
Now define the graphS as follows. It consists of every edge u→v such that (1) u→v is an edge in G , and (2) d(s,v)=d(s,u)+w(u,v) .
The graphS has some convenient properties:
Every shortest path froms to t in G exists as a path in S : a shortest path s=v0,v1,v2,…,vk=t in G has the property that d(s,vi+1)=d(s,vi)+w(vi,vi+1) , so the edge vi→vi+1 is present in S .
Every path inS from s to t is a shortest path in G . In particular, consider any path in S from s to t , say s=v0,v1,v2,…,vk=t . Its length is given by the sum of the weights of its edges, namely ∑ki=1w(vi−1,vi) , but by the definition of S , this sum is ∑ki=1(d(s,vi)−d(s,vi−1) , which telescopes to d(s,t)−d(s,s)=d(s,t) . Therefore, this path is a shortest path from s to t in G .
Finally, the absence of zero-weight edges inG implies that S is a dag.
Step 2: sample a random path. Now we can throw away the weights on the edges inS , and sample a random path from s to t in S .
To help with this, we will do a precomputation to computen(v) for each vertex v in S , where n(v) counts the number of distinct paths from v to t . This precomputation can be done in linear time by scanning the vertices of S in topologically sorted order, using the following recurrence relation:
wheresucc(v) denotes the successors of v , i.e., succ(v)={w:v→w is an edge in S} , and where we have the base case n(t)=1 .
Next, we use then(⋅) annotation to sample a random path. We first visit node s . Then, we randomly choose one of the successors of s , with successor w weighted by n(w) . In other words:
To choose a random path, we repeatedly iterate this process: i.e.,v0=s , and vi+1= (vi) . The resulting path is the desired path, and it will be sampled uniformly at random from all shortest paths from s to t .
choosesuccessor
Hopefully this helps you understand Realz Slaw's solution more easily. All credit to Realz Slaw for the beautiful and clean solution to this problem!
The one case this doesn't handle is the case where some edges have weight 0 or negative weight. However, the problem is potentially not well-defined in that case, as you can have infinitely many shortest paths.
sumber