[英]Dijkstra's algorithm for longest path
編輯2:這可能為時已晚,但我想出了問題,就是我。 我誤解了這個項目,它要求最大的帶寬路徑不是最長的路徑。 這是不同的,但直到現在我才知道。 因此,基本上在任何帶寬路徑問題(無論是最大還是最小)中,權重都不會累積,路徑值由路徑中的最小權重確定。 將其視為管道的路徑,水流量由沿路徑的最細管道決定。
編輯1:我修復了PQ問題,但仍無法正常工作。
這是一項任務(我承認),但如果我不提交,我可能會失敗整個課程。 我們應該修改Dijkstra的算法來計算最長的SIMPLE路徑而不是最短的路徑。 我無法找到解決方案。 我搜索了互聯網,發現了這個問題 (甚至是同樣的問題)。
但是當我運行它時,它會產生不正確的值。 有什么我想念的嗎? 為什么它甚至不能與前任相加呢? 為什么用min?
有關圖表的信息:1。我們隨機生成圖表,使每個節點連接到大約25%的其他節點。 2.權重是積極的。 3.圖中有25個節點。
問題是“路由算法是在圖中找到最大帶寬路徑的算法。它基於使用Max-Heap結構修改Dijkstra算法”。 有什么技巧可以幫助嗎?
public class MaxDijkstra {
Graph graph;
PriorityQueue<Node> queue;
public MaxDijkstra(Graph graph, Node s){
this.graph = graph;
s.addAttribute("ui.class", "start");
queue = new PriorityQueue<>(new Comparator<Node>(){
@Override
public int compare(Node n1, Node n2) {
if(Utils.getNodeBW(n1) == Utils.getNodeBW(n2)){
return 0;
}else if(Utils.getNodeBW(n1) < Utils.getNodeBW(n2)){
return 1;
}else{
return -1;
}
}
});
// init
for(Node n : graph){
Utils.setNodeBW(n, 0);
}
Utils.setNodeBW(s, Float.POSITIVE_INFINITY);
// add to Q
for(Node n : graph){
queue.add(n);
}
while(!queue.isEmpty()){
Node u = queue.remove();
Iterator<Node> iterator = u.getNeighborNodeIterator();
while(iterator.hasNext()){
Node v = iterator.next();
float min = Float.min(Utils.getNodeBW(u), Utils.getEdgeBW(u.getEdgeBetween(v)));
if(min > Utils.getNodeBW(v)){
Utils.setNodeBW(v, min);
Utils.setPreOfNode(v, u);
}
}
// validate PQ
// I know it is not good, just for debuggin now
// I will implemnt my own PQ later
List<Node> list = new ArrayList<>();
while(!queue.isEmpty()){
Node w = queue.remove();
list.add(w);
}
for(Node w : list){
queue.add(w);
}
}
}
public void printInfo(){
for(Node n : graph){
System.out.println("N="+n.getId()+" D="+Utils.getNodeBW(n)+" pre="+ (Utils.getPreOfNode(n) == null ? "NIL" : Utils.getPreOfNode(n).getId()) );
}
}
/**
* Just to colourise the path
* @param target
*/
public void backtrack(Node target){
target.addAttribute("ui.class", "end");
Node currunt = target;
Node pre = Utils.getPreOfNode(currunt);
while(pre != null){
currunt.getEdgeBetween(pre).addAttribute("ui.class", "route");
currunt = pre;
pre = Utils.getPreOfNode(currunt);
}
}
謝謝大家。
你不能使用Dijkstra的算法來找到最長的簡單路徑。 這個問題是NP難的。 事實上,沒有已知的多項式解決方案。
如果圖形相對較小,則可以使用動態編程來獲得O(2^n * poly(n))
解,這對於n~20-30是可行的(狀態是訪問頂點的掩模和最后一個頂點。如果可能的話,轉換是添加一個頂點)。
如果圖形很大,您可以使用不同的啟發式和近似值與局部優化技術相結合來獲得一個好的(但不一定是最優的)解決方案。
嘗試將所有權重乘以-1以使所有權重為負。 然后你可以使用Floyd-Warshall算法。 Floyd-Warshall算法在沒有循環的圖中使用負權重。 因此,使用Floyd-Warshall查找最小路徑,當乘以-1時,將是原始圖形中的最大路徑。
您無法更改優先級隊列中已有的元素。 通常對於Dijkstra,您需要一個decrease key
功能,但是庫中的那個不支持,所以您可以使用不同的BW值將節點多次重新插入到pq中。 像這樣的東西(認為這是偽代碼:))
PriorityQueue<pair<Node, int>> queue;
public MaxDijkstra(Graph graph, Node s){
queue = new PriorityQueue<>(new Comparator<pair<Node, int>>(){
@Override
public int compare(pair<Node, int> n1, pair<Node, int> n2) {
return n1.second > n2.second;
}
});
// init
for(Node n : graph){
Utils.setNodeBW(n, 0);
}
Utils.setNodeBW(s, Integer.MAX_VALUE);
// add to Q
for(Node n : graph){
queue.add({n, n.getNodeBW()});
}
while(!queue.isEmpty()){
pair<Node, int> u = queue.remove();
if (u.second < u.first.getNodeBW()) continue; //important - skip if you already saw better value
Iterator<Node> iterator = u.getNeighborNodeIterator();
while(iterator.hasNext()){
Node v = iterator.next();
int min = Integer.min(Utils.getNodeBW(u), Utils.getEdgeBW(u.getEdgeBetween(v)));
if(min > Utils.getNodeBW(v)){
Utils.setNodeBW(v, min);
queue.insert({v, min});
}
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.