微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

弗洛伊德算法写的最短路径有什么问题?

如何解决弗洛伊德算法写的最短路径有什么问题?

我使用 Floyd 算法写出最短路径。数据是这个图,但是得到的path[0][7]是5而不是4,为什么?

graph data

D[][]

path[][]

D中0到9的路径权重没有错,但是path[0][7]错了


Floyd 算法:

bool Floyd( MGraph Graph,WeightType D[][MaxVertexnum],Vertex path[][MaxVertexnum] )
{
    //Initialize path[] and distance
    for( int i = 0; i < Graph->Nv; i++ ){
        for( int j = 0; j < Graph->Nv; j++ ){
            D[i][j] = Graph->G[i][j];
            path[i][j] = -1;
        }
    }

    //Floyd algorithm
    for( int k = 0; k < Graph->Nv; k++ ){
        for( int i = 0; i < Graph->Nv; i++ ){
            for( int j = 0; j < Graph->Nv; j++ ){
                if( D[i][k] + D[k][j] < D[i][j] ){
                    D[i][j] = D[i][k] + D[k][j];

                    if( i == j && D[i][j] < 0 )
                        return false;                

                    path[i][j] = k;
                }
            } 
        }
    }

    return true;
}

完整代码

#include<stdlib.h>
#include<stdio.h>
#include<stdbool.h>

#define MaxVertexnum 100   //Maximum of 100 vertices
#define INFINITY 65535      //Define infinity
typedef int Vertex;
typedef int WeightType;
typedef int DataType;


// Vertex
struct Gnode{
    int Nv;     //the number of vertex
    int Ne;     //the number of edge
    WeightType G[MaxVertexnum][MaxVertexnum];   //Adjacency matrix
    DataType Data[MaxVertexnum];    //Vertex data
};
typedef struct Gnode *MGraph;

// Edge
struct Enode{
    Vertex V1,V2;      //Directed edges <V1,V2>
    WeightType Weight;      //Weight
};
typedef struct Enode *Edge;

//  Initialize an edgeless graph with Vertexnum vertices
MGraph CreatGraph( int Vertexnum )
{
    Vertex V,W;
    MGraph Graph;

    Graph = (MGraph)malloc(sizeof(struct Gnode));
    Graph->Nv = Vertexnum;
    Graph->Ne = 0; 
    for( V = 0; V < Graph->Nv; V++ ){
        for( W = 0; W < Graph->Nv; W++ ){
            Graph->G[V][W] = INFINITY;
        }
    }

    return Graph;
}

void InsertEdge( MGraph Graph,Edge E )
{
    Graph->G[E->V1][E->V2] = E->Weight;
    Graph->G[E->V2][E->V1] = E->Weight;
}

MGraph BuildGraph()
{
    MGraph Graph;
    Edge E;
    Vertex V;
    int Nv;

    //Initialize the Graph
    printf("Enter the number of vertices:");
    scanf("%d",&Nv);
    Graph = CreatGraph( Nv );
    

    //Input Edge
    printf("\nEnter the number of edges:");
    scanf("%d",&(Graph->Ne));
    if( Graph->Ne != 0 ){
        E = (Edge)malloc(sizeof(struct Enode));
        for( int i = 0; i < Graph->Ne; i++ ){
            scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
            InsertEdge( Graph,E );
        }
    }

    //vertex data
    printf("\nEnter vertex data:\n");
    for( V = 0; V < Graph->Nv; V++ ){
        scanf(" %d",&(Graph->Data[V]));
    }

    return Graph;
}

bool Floyd( MGraph Graph,Vertex path[][MaxVertexnum] )
{
    //Initialize path[] and distance
    for( int i = 0; i < Graph->Nv; i++ ){
        for( int j = 0; j < Graph->Nv; j++ ){
            D[i][j] = Graph->G[i][j];
            path[i][j] = -1;
        }
    }

    //Floyd algorithm
    for( int k = 0; k < Graph->Nv; k++ ){
        for( int i = 0; i < Graph->Nv; i++ ){
            for( int j = 0; j < Graph->Nv; j++ ){
                if( D[i][k] + D[k][j] < D[i][j] ){
                    D[i][j] = D[i][k] + D[k][j];

                    if( i == j && D[i][j] < 0 )
                        return false;                

                    path[i][j] = k;
                }
            } 
        }
    }

    return true;
}


int main()
{
    MGraph Graph;
    Graph = BuildGraph();

    printf("\nThis is the adjacency matrix:\n");
    for( int i = 0; i < Graph->Nv; i++ ){
        for( int j = 0; j < Graph->Nv; j++ ){
            printf("%-8d",Graph->G[i][j]);
        }
        printf("\n");
    }

    //Shortest path
    int D[MaxVertexnum][MaxVertexnum];
    int path[MaxVertexnum][MaxVertexnum];
    Floyd( Graph,D,path );

    Vertex V1,V2;
    printf("starting point:");
    scanf("%d",&V1);
    printf("End point:");
    scanf("%d",&V2);

    
    
    int v1,v2; 
    v1 = V1;
    v2 = V2;

    while( path[v1][v2] != -1 ){
        printf("%d<-",Graph->Data[path[v1][v2]] );
        v2 = path[v1][v2];
    }
    
    return 0;
}

测试数据:

10
17
0 1 2
0 3 5
1 2 5
1 3 2
2 4 8
2 5 4
3 5 4
3 6 2
4 5 2
4 7 5
5 6 3
5 7 9
5 8 6
6 8 7
7 8 3
7 9 4
8 9 8
0
1
2
3
4
5
6
7
8
9

解决方法

path[i][j] = k; 中的 Floyd 行没有考虑到从 kj 的最短路径(到目前为止)可能是通过一个中间节点这一事实。将该行更改为 path[i][j] = path[k][j] == -1 ? k : path[k][j]; 可以解决该问题。

我还建议将节点到自身的距离设置为 0。这可以通过将行 D[i][j] = Graph->G[i][j]; 更改为 D[i][j] = i == j ? 0 : Graph->G[i][j]; 来实现。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。