2012-11-24 79 views
2

問題編輯,現在我只想知道是否可以使用隊列來改進算法。優化dijkstra實現

我發現這個實現混合代價最大流算法,它採用的Dijkstra:http://www.stanford.edu/~liszt90/acm/notebook.html#file2

要去這裏粘貼的情況下,它就會在互聯網虛空丟失:

// Implementation of min cost max flow algorithm using adjacency 
// matrix (Edmonds and Karp 1972). This implementation keeps track of 
// forward and reverse edges separately (so you can set cap[i][j] != 
// cap[j][i]). For a regular max flow, set all edge costs to 0. 
// 
// Running time, O(|V|^2) cost per augmentation 
//  max flow:   O(|V|^3) augmentations 
//  min cost max flow: O(|V|^4 * MAX_EDGE_COST) augmentations 
//  
// INPUT: 
//  - graph, constructed using AddEdge() 
//  - source 
//  - sink 
// 
// OUTPUT: 
//  - (maximum flow value, minimum cost value) 
//  - To obtain the actual flow, look at positive values only. 

#include <cmath> 
#include <vector> 
#include <iostream> 

using namespace std; 

typedef vector<int> VI; 
typedef vector<VI> VVI; 
typedef long long L; 
typedef vector<L> VL; 
typedef vector<VL> VVL; 
typedef pair<int, int> PII; 
typedef vector<PII> VPII; 

const L INF = numeric_limits<L>::max()/4; 

struct MinCostMaxFlow { 
    int N; 
    VVL cap, flow, cost; 
    VI found; 
    VL dist, pi, width; 
    VPII dad; 

    MinCostMaxFlow(int N) : 
    N(N), cap(N, VL(N)), flow(N, VL(N)), cost(N, VL(N)), 
    found(N), dist(N), pi(N), width(N), dad(N) {} 

    void AddEdge(int from, int to, L cap, L cost) { 
    this->cap[from][to] = cap; 
    this->cost[from][to] = cost; 
    } 

    void Relax(int s, int k, L cap, L cost, int dir) { 
    L val = dist[s] + pi[s] - pi[k] + cost; 
    if (cap && val < dist[k]) { 
     dist[k] = val; 
     dad[k] = make_pair(s, dir); 
     width[k] = min(cap, width[s]); 
    } 
    } 

    L Dijkstra(int s, int t) { 
    fill(found.begin(), found.end(), false); 
    fill(dist.begin(), dist.end(), INF); 
    fill(width.begin(), width.end(), 0); 
    dist[s] = 0; 
    width[s] = INF; 

    while (s != -1) { 
     int best = -1; 
     found[s] = true; 
     for (int k = 0; k < N; k++) { 
     if (found[k]) continue; 
     Relax(s, k, cap[s][k] - flow[s][k], cost[s][k], 1); 
     Relax(s, k, flow[k][s], -cost[k][s], -1); 
     if (best == -1 || dist[k] < dist[best]) best = k; 
     } 
     s = best; 
    } 

    for (int k = 0; k < N; k++) 
     pi[k] = min(pi[k] + dist[k], INF); 
    return width[t]; 
    } 

    pair<L, L> GetMaxFlow(int s, int t) { 
    L totflow = 0, totcost = 0; 
    while (L amt = Dijkstra(s, t)) { 
     totflow += amt; 
     for (int x = t; x != s; x = dad[x].first) { 
     if (dad[x].second == 1) { 
      flow[dad[x].first][x] += amt; 
      totcost += amt * cost[dad[x].first][x]; 
     } else { 
      flow[x][dad[x].first] -= amt; 
      totcost -= amt * cost[x][dad[x].first]; 
     } 
     } 
    } 
    return make_pair(totflow, totcost); 
    } 
}; 

我的問題是否可以通過使用Dijkstra()中的優先級隊列來改進。我試過,但我無法讓它正常工作。 其實我懷疑在Dijkstra它應該在相鄰節點上循環,而不是所有節點...

非常感謝。

+0

1)目前尚不清楚你要完成什麼2)標題與算法不匹配。這是最低成本還是最高流量? – Haile

+0

要重新說明我的問題。 – Papipo

回答

1

當然可以通過使用minheap來改進Dijkstra的算法。在將頂點放入最短路徑樹並處理(即標籤)所有相鄰頂點之後,我們的下一步是選擇具有最小標籤的頂點,而不是樹中的頂點。
這是讓人想起minheap的地方。我們不是按順序掃描所有頂點,而是從堆中提取最小元素並對其進行重構,這需要O(logn)時間vs O(n)。請注意,堆將僅保留那些尚未位於最短路徑樹中的頂點。但是,如果我們更新標籤,我們應該能夠以某種方式修改堆中的頂點。