求最短路径(迪杰斯特拉算法,弗洛伊德算法)

迪杰斯特拉算法

从某个顶点到其余各顶点的最短路径(  o(n的平方))

举个例子:

问题:求出下图中顶点1到其余各顶点的最短路径

题目1
DIST

这个图的计算方法,

比如s是1的时候,DIST就是1到各个顶点的最短距离,不能到达就是无穷,可以确定最短的是1->5

然后,s就是1,5,DIST就是从5到其他顶点的距离+上图1->5的距离,和1时候的DIST对比,比他小填入就可以了,否则填上面的

...其他类似

从图中可以看出顶点1到其他顶点的最短路径依次是20,31,28,10,17,25,35,按迪杰斯特拉算法所选顶点依次是5,6,2,7,4,3,8

代码:

#include

using namespace std;

int main(){

    int m,n;//m是有多少个顶点,n是从哪个顶点开始

    cin>>m>>n;

    int p[m][m];

    for(int i=0;i

        for(int j=0;j

            cin>>p[i][j];

        }

    }

    int d[m];//用来存储n顶点到其他顶点的最短路径,输出从1到m-1的数,默认是0

    for(int i=0;i

        d[i]=0;

    }

    //要想得到其他最短路径,需要循环m-1次,每次确定一个最短路径

    int k=m-1;

    int v[m];//看是否已经确定是最短路径了,初始化为0如果是1标识确定了

    for(int i=0;i

        v[i]=0;

    }

    int p1=n;

    int min;

    int min_i;

    bool b=true;

    for(int i=0;i

        if(i==n){

            continue;

        }

        if(p[n][i]!=0&&b){//找到第一个非0的元素标识为最小的

            min=p[n][i];

            min_i=i;

            b=false;

            d[i]=p[n][i];

        }

        if(!b&&p[n][i]!=0){

            if(p[n][i]

                min=p[n][i];

                min_i=i;

            }

            d[i]=p[n][i];

        }

    }

    v[min_i]=1;//标识确定了最短路径的下标

    n=min_i;//有最小的从最小的那个开始,和上一次的d[i]对比,看是否有比他小的

    k=k-1;

    for(int i=0;i

        cout<

    }

    cout<

    while(k--){//进行m-1次遍历,确定最小

        for(int i=0;i

            if(v[i]==1||i==p1){

                continue;

            }

            if(p[n][i]!=0&&d[i]!=0){

                if(p[n][i]+d[min_i]

                    d[i]=p[n][i]+d[min_i];

                }

            }

            if(p[n][i]!=0&&d[i]==0){

                d[i]=p[n][i]+d[min_i];

            }

        }

        b=true;

        //确定d[i]不为0的最小下标并且v[i]==0的下标

        for(int i=0;i

            if(d[i]!=0&&b&&v[i]==0){//找到第一个非0的元素标识为最小的

                min=d[i];

                min_i=i;

                b=false;

            }

            if(!b&&d[i]!=0&&v[i]==0){

                if(d[i]

                    min=d[i];

                    min_i=i;

                }

            }

        }

        v[min_i]=1;

        n=min_i;

        for(int i=0;i

            cout<

        }

        cout<

    }

    for(int i=0;i

        if(i!=p1){

            if(d[i]==0){

                cout<<-1<<" ";

            }else{

                cout<

            }

        }

    }

    return 0;

}

结果:

结果1

弗洛伊德算法

各个顶点之间的最短距离

举例:

有一个带权有向图,用弗洛伊德算法求各顶点间的最短距离的矩阵序列A1,A2,A3

题目2

每一对顶点之间的路径,初始用A(-1)标识:

A(-1)

求A(0),A(1),A(2),

A(0)在A(-1)的基础上求A[i][0]+A[0][j]

比较好使不易出错的方法:先找出第0列的元素,然后找出第0行的元素,然后加起来,构造一个新的矩阵,这个矩阵和A(-1)矩阵比较,找出其中比A(-1)矩阵中的元素小的,然后代替A(-1)中的元素,就是A(0)矩阵了

A(1)在A(0)的基础上

A(2)在A(1)的基础上

A(0)
A(1)
A(2)

代码:

#include

using namespace std;

int main(){

    int n;

    cin>>n;

    int p[n][n];

    int v[n][n];//=1就是无穷

    for(int i=0;i

        for(int j=0;j

            cin>>p[i][j];

            if(p[i][j]==0&&i!=j){

                v[i][j]=1;

            }else{

                v[i][j]=0;

            }

        }

    }

    int m=n;

    int k=0;

    while(m--){

        int temp[n][n];//临时数组

        for(int i=0;i

            for(int j=0;j

                if(v[k][j]==1||i==j||v[i][k]==1){//如果是无穷,或者是对角线上的值

                    temp[i][j]=p[i][j];

                }else{

                    temp[i][j]=p[k][j]+p[i][k];

                }

            }

        }

        k++;

//        cout<<"temp数组:"<

//        for(int i=0;i

//            for(int j=0;j

//                cout<

//            }

//            cout<

//        }

//        cout<

        for(int i=0;i

            for(int j=0;j

                if(i==j){

                    continue;

                }else{

                    if(v[i][j]==1){//是无穷

                        p[i][j]=temp[i][j];

                        if(p[i][j]!=0){

                            v[i][j]=0;

                        }

                    }else{//不是无穷

                        if(temp[i][j]

                            p[i][j]=temp[i][j];

                        }

                    }

                }

            }

        }

//        cout<<" p数组"<

//        for(int i=0;i

//            for(int j=0;j

//                cout<

//            }

//            cout<

//        }

    }

    for(int i=0;i

        for(int j=0;j

            if(i==j){

                cout<

                continue;

            }else if(p[i][j]==0){

                p[i][j]=-1;

            }

            cout<

        }

        cout<

    }

    return 0;

}

结果:

你可能感兴趣的:(求最短路径(迪杰斯特拉算法,弗洛伊德算法))