【清明】最短路

最短路是很神奇的东西
//图上DP

都知道边有边权,可正可负
最短路算法的主体思想是通过对图的操作,使得两点间的最短路径被求出
多源最短路处理多个起点终点
单源最短路处理一个起点多个终点

floyd//多源最短路
spfa
spfa_slf(双端队列优化
dijkstra
dijkstra_heap(堆优化

//其实搜索也行2333//被打飞
0.无权图
无权图:各边权值相等的图// !=权值为0
@BFS 遍历全图,分层,ans = 层数*权值;
DFS不行 举个例子:

1.floyd
三重循环 k i j
基于DP思想,最外层k代表以k作为中转站的从i到j的最短路,即i->k->j;
依次循环更新

void floyd()
{
    for(int k = 1; k <= n; k ++)
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
}

2.spfa /spfa_slf

依次枚举边 能更新就更新
特点是每个点经过次数不定

双端队列优化:每次选取更小边进行更新

spfa可以判负环
退出必须队列为空,不能中途退出

spfa:

queue < int > q;
void spfa(int s){
    while(!q.empty()) q.pop();
    memset(use,0,sizeof(use));
    memset(dis,0x3f,sizeof(dis));
    use[s] = true; dis[s] = 0;
    q.push(s);

    while(!q.empty()){
        int u = q.front(); q.pop();
        use[u] = false;
        for(int i = first[u]; i != -1; i = nxt[i]){
            int w = l[i].t;
            if(dis[w] > dis[u] + l[i].v){
                dis[w] = dis[u] + l[i].v;
                if(use[w]) continue;
                q.push(w); use[w] = true;
            }
        }
    }
    return;
}

spfa_slf

deque < int > q;
void spfa(int s){
    while(!q.empty()) q.pop_front();
    memset(use,0,sizeof(use));
    memset(dis,0x3f,sizeof(dis));
    use[s] = true; dis[s] = 0;
    q.push_front(s);

    while(!q.empty()){
        int u = q.front(); q.pop_front();
        use[u] = false;
        for(int i = first[u]; i != -1; i = nxt[i]){
            int w = l[i].t;
            if(dis[w] > dis[u] + l[i].v){
                dis[w] = dis[u] + l[i].v;
                if(use[w]) continue;
                if(q.empty() || dis[w] < dis[q.front()]) q.push_front(w);
                else q.push_back(w);
            }
        }
    }
    return;
}

/*
有种特殊的优化叫做spfa_cy
学名:序号优化
如果当前点序号比队首序号小,就把它放在队首
不然就放队尾
玄学优化
*/

3.dij/dij_heap
每个点只入队一次,更新所有能更新的点
堆优化 每次优先更新更短的

可以中途退出

int dij(int s,int e)
{
    memset(use,0,sizeof(use));
    while(!q.empty())   q.pop();
    q.push((re){s,0});
    while(!q.empty())
    {
        re us = q.top();
        q.pop();
        int u = us.u;
        if(u == e)  return us.v;
        if(use[u])  continue;
        use[u] = true;
        for(int i = first[u]; i != -1; i = next[i])
        {
            int w = l[i].t;
            int rs = us.v + l[i].v;
            q.push((re){w,rs});
        }
    }
    return -1;
}

你可能感兴趣的:(===【清明】===)