图论初步——最短路(1)

最短路

分类

单源最短路:从一个点到其他所有点的最短路
算法: D i j k s t r a , s p f a Dijkstra,spfa
多源最短路:从所有点到另外点的最短路
算法: F l o y d Floyd

Floyd算法

时间复杂度: O ( n 3 ) O(n^3)
适用范围: 0 < = n < = 300 0<=n<=300

思想

类似于 D P DP
寻找 2 2 个点 i , j i,j ,判断是否存在一个中间点 k k ,使得 i > k > j i->k->j 的距离小于 i > j i->j 的距离
由此得到方程式
d [ i ] [ j ] = m i n ( d [ i ] [ k ] + d [ j ] [ k ] ) , k [ 1 , n ] d[i][j]=min(d[i][k]+d[j][k]),k∈[1,n]

核心代码
memset(d,127,sizeof(d));
for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
        for(int k=1;k<=n;k++){
            if(i==j||i==k||j==k)  continue;
            d[i][j]=min(d[i][k]+d[j][k],d[i][j]);
        }
    }
}

Dijkstra算法初步

时间复杂度: O ( n 2 ) O(n^2) (可以优化到 O ( ( n + m ) l o g n ) O((n+m)logn) )适用范围
适用范围: 1 0 4 10^4 1 0 6 10^6

思想

考虑在一个无负权边的图上(实际上是没有负环),如果一个点在一些点中离起点的距离最近,那么其他点必定无法更新起点到它的最短路。
我们先将距离赋一个极大值,然后用起点更新其他点的距离,此时标记起点。
然后找到剩余点中距离最小的点,标记它,用它来更新剩下的点。
被标记的点不被选择,不被更新,当所有点被标记后,输出每个点到起点的距离,即为最短路。

Example

以上图为例:
首先, d [ 1 ] = 0 d[1]=0 ,其余均为极大值,所以用 1 1 来更新,标记点 1 1
此时 d [ 2 ] = 2 , d [ 3 ] = 6 , d [ 5 ] = 4 d[2]=2,d[3]=6,d[5]=4
d [ 2 ] d[2] 最小,标记点 2 2
此时 d [ 3 ] = 5 , d [ 4 ] = 7 d[3]=5,d[4]=7
d [ 5 ] d[5] 最小,标记点 5 5
此时 d [ 6 ] = 6 , d [ 7 ] = 7 d[6]=6,d[7]=7

核心代码
memset(vis,false,sizeof(vis));
memset(d,127,sizeof(d));
for(int i=1;i<=n;i++){
    int minn=2147483647,num;
    for(int j=1;j<=n;j++){
        if(!vis[j]&&d[j]<minn){
           minn=d[j];
           num=j;
        }
    }
    vis[num]=true;
    for(int e=first[num];e;e=nxt[e]){
        int v=to[e];
        if(d[v]>d[num]+w[e])
          d[v]=d[num]+w[e];
    }
}
发布了45 篇原创文章 · 获赞 18 · 访问量 4766

猜你喜欢

转载自blog.csdn.net/wljoi/article/details/98741669