多元最短路径——Floyd-Warshall算法

多源最短路径——Floyd-Warshall算法

首先分析这张图

就拿从1到3,可以直接1->3,也可以1->2->3,我们发现,通过一个“中转”的2,1->3路径会变短。

可以在一个路径中插入另一个顶点,这样可能会比直接过去的路径更短,假设每个顶点都经过顶点2中转,可以有这样的语句。

我们用二维数组graph[][]存储图

int i;
int j;
for(i=1;i<=n;++i){

    for(j=1;j<=n;++j){

        if(graph[i][j]>graph[i][2]+graph[2][j])//通过中转路径变短了
            graph[i][j]=graph[i][2]+graph[2][j];//则将从i到j的路径长度改为中转后的较短路径
    }
}

中转顶点可以是图中的任意一个顶点,所以将所有顶点做一次中转顶点 即可以将用一个循环变量来当作中转点

int i;
int j;
int k;
for(k=1;k<=n;++k){
    for(i=1;i<=n;++i){

        for(j=1;j<=n;++j){

            if(graph[i][j]>graph[i][2]+graph[2][j])//通过中转路径变短了
                graph[i][j]=graph[i][2]+graph[2][j];//则将从i到j的路径长度改为中转后的较短路径
        }
    }
}

完整代码如下:

#include 

const int INF=999999999;

int main(void){

    int graph[10][10];
    int n,m;//n个顶点,m条边
    printf("请输入定点数与边数:");
    scanf("%d%d",&n,&m);

    //初始化二维数组 
    for(int i=1;i<=n;++i){

        for(int j=1;j<=n;++j){

            graph[i][j]=INF;
        }
        graph[i][i]=0;
    }

    for(int i=1;i<=m;++i){

        int s,e;
        printf("第%d条边及其权值:",i );
        scanf("%d%d",&s,&e);
        scanf("%d",&graph[s][e]); 
    }

    /*********核心部分*********/
    int i,j,k;
    for(i=1;i<=n;++i)
        for(j=1;j<=n;++j)
            for(k=1;k<=n;++k){

                if(graph[j][i]!=INF && graph[i][k]!=INF && graph[j][i]+graph[i][k]%d  %d\n",i,j,graph[i][j]);
        }

    return 0;
}

虽然用插一个中转点来引出这段代码,但是最短路径不一定全是只会有一个中转点。

举个栗子:假设一个最短路径是1->3->5->7,上述算法先找出从1到5的最短路径是1->3->5,现在的graph[1][5]被更新成为了grap[1][3]+graph[3][5],接下来计算1->7的最短路径时上述算法算出的时1->5->7,这里的1->5实际上是1->3->5。这样说可能有点乱,希望的对理解这个算法有点帮助。

你可能感兴趣的:(简单算法)