最短路算法

来源:互联网 发布:node-http-proxy原理 编辑:程序博客网 时间:2024/06/06 09:45

弗洛伊德(Floyd)

dist[k][i][j]表示利用到1...k作为中间点,ij的最短路。

for(int k = 1; k <= n; ++k) // 对k的枚举也可以写在最里层    for(int i = 1; i <= n; ++i)        for(int j = 1; j <= n; ++j)            dist[k][i][j] = min(dist[k][i][j], dist[k-1][i][k] + dist[k-1][k][j]);

这样表示状态的话相当于一个动态规划,此时k在最里层或是最外层枚举都是一样的。但我们通常是用dist[i][j]表示状态,这个时候k就必须在最外层枚举。

for(int k = 1; k <= n; ++k) // 对k的枚举此时只能写在最外层    for(int i = 1; i <= n; ++i)        for(int j = 1; j <= n; ++j)            dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

确定步数后的最短路

dist[t][i][j]t步后ij的最短距离,可以用类似矩阵乘法统计路径方案数的方法处理这个问题。

// dist[1][i][j] 为原图for(int t = 2; t <= n; ++t)    for(int k = 1; k <= n; ++k) // 对k的枚举也可以写在最里层        for(int i = 1; i <= n; ++i)            for(int j = 1; j <= n; ++j)                dist[t][i][j] = min(dist[t][i][j], dist[t-1][i][k] + dist[1][k][j]);

这样计算m步后的最短距离时间复杂度是O(n3m),为了在O(n3logm)的时间复杂度下解决这个问题,我们可以把m拆成多个2t的和。用dist[t][i][j]表示2t步后的最短距离。

// dist[0][i][j] 为原图for(int t = 1; t <= n; ++t)    for(int k = 1; k <= n; ++k) // 对k的枚举也可以写在最里层        for(int i = 1; i <= n; ++i)            for(int j = 1; j <= n; ++j)                dist[t][i][j] = min(dist[t][i][j], dist[t-1][i][k] + dist[t-1][k][j]);

迪杰斯特拉(Dijkstra)加堆

priority_queue<pair<int, int> > que;bool popped[maxn];void dijkstra(int s){    for(int i = 1; i <= n; ++i) popped[i] = false;    dist[s] = 0;    que.push(make_pair(-dist[s], s));    while(!que.empty()){        int u = que.top().second;        que.pop();        if(popped[u]) continue;        popped[u] = true;        for(int l = 0; l < mp[u].size(); ++l){            int v = mp[u][l];            if(dist[v] > dist[u] + 1){                dist[v] = dist[u] + 1;                que.push(make_pair(-dist[v], v));            }        }    }}
0 0
原创粉丝点击