最短路板子

堆优化dij

  • Dijkstra基于贪心思想,指适用为边权都是非负数的图
  • 而且这样写不能用于求最长路,需要进行优化,求最长路可以用SPFA
    • 最长路没有子结构,子段最长不一定总的最长。如图:

Code

priority_queue< pair<int, int> > q;
//这里两个'>'尽量不要写在一起,有的编译环境会CE
int d[N]; 
bool v[N];
void dij(int u) {
    memset(v, 0, sizeof(v));
    memset(d, 0x3f, sizeof(d));
    d[u] = 0;
    q.push(make_pair(0, u));
    while (!q.empty()) {
        int x = q.top().second; q.pop();
        if (v[x]) continue;
        v[x] = 1;
        for(int i = head[x]; i; i = e[i].next) {
            int y = e[i].t;
            if (d[y] > d[x] + e[i].d) {
                d[y] = d[x] + e[i].d;
                q.push(make_pair(-d[y], y));
                //默认是从大到小排序,变成负数后就是从小到大了
            }
        }
    }
}

spfa

  • SPFA在随机图上时间效率为\(O(km)\)级别, 其中\(k\)是个较小的常数
    但在特殊构造的图上,可能会退化为\(O(nm)\),必须谨慎使用

Code

queue<int> q;
void Spfa(int u) {
    memset(d, 0x3f, sizeof(d));
    d[u] = 0;
    q.push(u); v[u] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop(); v[x] = 0;
        for (int i = head[x]; i; i = e[i].next) {
            int y = e[i].t;
            if (d[y] > d[x] + e[i].d) {
                d[y] = d[x] + e[i].d;
                if (v[y]) continue;
                q.push(y); v[y] = 1;
            }
        }
    }
}

双端队列优化spfa

  • SPFA还可以通过双端队列进行SLF优化(改变的地方我都有标注)

Code

deque<int> q;
void Spfa(int u) {
    memset(d, 0x3f, sizeof(d));
    d[u] = 0;
    q.push_back(u); v[u] = 1;//这里
    while (!q.empty()) {
        int x = q.front();
        q.pop_front(); v[x] = 0;//这里
        for (int i = head[x]; i; i = e[i].next) {
            int y = e[i].t;
            if (d[y] > d[x] + e[i].d) {
                d[y] = d[x] + e[i].d;
                if (v[y]) continue;
                if (d[y] <= d[q.front()]) q.push_front(y);
                //这里是最主要的地方,加入的元素如果比队首小,就放在队首
                else q.push_back(y); //这里
                v[y] = 1;
            }
        }
    }
}
posted @ 2020-05-26 12:51  Shawk  阅读(123)  评论(0编辑  收藏  举报