图论-最短路算法

求最短路暂时掌握了4种,但感觉就dijkstra复杂度能用;

1   floyd算法:

就是暴力的三重循环,以每个点为中转点,每次遍历所有的点,看看能不能通过这个中转点更新最短路径;

优点:n<200时用这种方法,用邻接矩阵存图 ,可求任意的两点的最短路;而且好写;

缺点:复杂度太高,O(n^3)的复杂的,太多不必要的计算;

void floyd(){
    //dis数组表示i到j的最短路径
    for(int k=0;k<n;k++)//重点,必须放在外面
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);

}
View Code

 2   bellman-floyd算法:

解决单源最短路,就是循环n次,每次检查每一条边,看看是否能通过邻居更新最短的路径

优点:n<1e7可以考虑这种方法,用结构体数组存图即可,然后这是并行式计算,循环怎么搞都行,

缺点:复杂度还是蛮高的,每个点  O(n*m)的复杂度;

void bellman(){
    int s,t;//s为起点,t为终点
    for(int i=1;i<=n;i++)dis[i]=inf;
    //dis数组表示所有点到s的最短路
    dis[s]=0;
    for(int k=1;k<=n;k++)
    for(int i=0;i<cnt;i++){
    int x=e[i].u,y=e[i].v;
    if(dis[x]>dis[y]+e[i].w){//更新距离
    dis[x]=dis[y]+e[i].w;
        }
    }
    cout<<dis[t];
}
View Code

3    SPFA  :

缺点:不稳点,

算法:和广搜很像;

学了再更新;

 4    dijkstra:

算法:基于贪心思想,就是每次更新之后,路径最短的那个点一定是最终的最短路径,因为借道去其他点必定比这个距离大;一次次迭代;

优点:考虑用邻接表存图,复杂度可以接受,而且稳定;解决单源最短路问题,复杂度O(m*log(n));

int dijkstra(){
    int s,t;//s表示起点,t表示终点
    for(int i=0;i<=maxn;i++)dis[i]=inf,done[i]=0;
    dis[s]=0;
    //dis表示每个点到s的最短路,done数组记录是否得到最短路
    priority_queue<node>Q;
    Q.push(node(s,0));
    while(!Q.empty()){
    node u=Q.top();
    Q.pop();
    if(done[u.id])continue;
    done[u.id]=1;
    for(int i=0;i<e[u.id].size();i++){
    edge y=e[u.id][i];
    if(done[y.v])continue;
    if(dis[y.v]>y.w+u.dis){
    dis[y.v]=y.w+u.dis;//更新邻居的最短路
    }
    Q.push(node(y.v,dis[y.v]));//把每个邻居节点扩充进来
    }

    }
    return dis[t];
}
View Code

判负圈的问题,学了再补充;

想的太多,做的太少;
原文地址:https://www.cnblogs.com/littlerita/p/12343890.html