gpt4 book ai didi

c++ - 优化 dijkstra 实现

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:52:22 24 4
gpt4 key购买 nike

问题已编辑,现在我只想知道是否可以使用队列来改进算法。

我发现了这个混合成本最大流算法的实现,它使用了 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 中它应该遍历相邻节点,而不是所有节点......

非常感谢。

最佳答案

Dijkstra 的算法肯定可以通过使用 minheap 来改进。在我们将一个顶点放入最短路径树并处理(即标记)所有相邻顶点后,我们的下一步是选择具有最小标签但尚未在树中的顶点。
这就是 minheap 想到的地方。我们不是按顺序扫描所有顶点,而是从堆中提取最小元素并重组它,这需要 O(logn) 时间 vs O(n)。请注意,堆将仅保留那些尚未在最短路径树中的顶点。然而,如果我们更新它们的标签,我们应该能够以某种方式修改堆中的顶点。

关于c++ - 优化 dijkstra 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13545173/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com