Dijkstra与Floyd 最短路问题

Dijkstra与Floyd算法解最短路问题(注意路径的保存,十分巧妙):

个人理解两个算法都有点动态规划的意思,都是用局部最优解展开求。
最好的关于Dijkstra的讲解与流程图还得是殷剑宏离散数学里面的。在这里做个笔记以免忘记。

这里写图片描述

[这里写图片描述

书中题目题目的解法:

Dijkstra解法:

结合上面题目并耐心走流程图表就可以理解。
这里写图片描述

/*离散数学P218*/ 
#include<iostream>
using namespace std;
const int maxnode=6;//最大点数 
const int maxline=9;//最大变数 
int dist[maxnode];
bool visit[maxnode];
int G[maxnode][maxnode];
int INF=0x7ffff;//无穷 
int path[maxnode];//保存路径
void Dijstra(int v0)
{
    for(int i=0;i<maxnode;i++){
        dist[i]=G[v0][i];//记录源点到所有点的距离 
        visit[i]=false;//所有点都标记为未访问
        path[i]=v0;//初始化指定所有节点的前驱结点都是自己 
    }

    dist[v0]=0;//标志当前距离为0 
    visit[v0]=true; //设置源点为已访问 
    int temp_maxnode=maxnode; 
    while(temp_maxnode--){//不断循环让查找深入(因为有visit[]是全局变量,所以可以继续) 
        int u;
        int mindist=INF;
        for(int i=0;i<maxnode;i++){//循环找出所有到源点的最短路的点 
            if(!visit[i]&&dist[i]<mindist){//如果没有被访问并且这个点比保存的最小值还要小 
                mindist=dist[i];
                u=i;
            }
        }

        visit[u]=true;//找到的最小的并标记为访问过。 

        for(int i=0;i<maxnode;i++) 
            if(!visit[i]&&dist[u]+G[u][i]<dist[i]){//如果源点到目的点的最小值+这个点到下一个点的距离<源点直接到下一个点的距离 

                dist[i]=dist[u]+G[u][i];//更新源点到这个点的最小距离 
                path[i]=u;
            }
    }
}

void printPath(int src,int end)
{
    while(src!=end){
        cout<<path[end]<<"->";
        end=path[end];
    }
}
int main()
{ 

    for(int i=0;i<maxnode;i++)
        for(int j=0;j<maxnode;j++)
        {
            G[i][j]=INF;
            if(i==j) G[i][j]=0;//自己到自己初始化为0 
        }
//  

    G[0][1]=4;  G[0][2]=2;
    G[1][2]=1;  G[1][3]=5;
    G[2][4]=10; G[2][3]=8;
    G[3][4]=2;  G[3][5]=6;
    G[4][5]=3;

    G[1][0]=4;  G[2][0]=2;
    G[2][1]=1;  G[3][1]=5;
    G[4][2]=10; G[3][2]=8;
    G[4][3]=2;  G[5][3]=6;
    G[5][4]=3;
    int node_src;

    scanf("%d",&node_src);

    Dijstra(node_src);
    for(int i=0;i<maxnode;i++)
        printf("%d ",dist[i]); 

    cout<<endl;
    for(int i=0;i<maxnode;i++){
        printPath(node_src,i);
        cout<<endl;
    }
    return 0;

} 

Floyd算法解此题:

如果只经过一个点1,判断是否能够收缩:

{
    for(j=1;j<=n;j++)
    {
        if ( e[i][j] > e[i][1]+e[1][j] )
              e[i][j] = e[i][1]+e[1][j];
    }
}

多个点(注意防止溢出):

for(int k=0;k<max_node;k++)
        for(int i=0;i<max_node;i++)
            for(int j=0;j<max_node;j++)
                if(!(G[i][k]==INF||G[k][j]==INF)&&G[i][k]+G[k][j]<G[i][j]){//加判断防止溢出
                    G[i][j]=G[k][j]+G[i][k];
                }

code:

#include<iostream> 
#include<vector>
using namespace std;
const int max_node=6;
int G[max_node][max_node];
int INF=0x7ffff;

int path[max_node][max_node];

void floyd()
{ 
    for(int i=0;i<max_node;i++)
        for(int j=0;j<max_node;j++)
            if(G[i][j]==INF)  path[i][j]=-1;
            else path[i][j]=i;//记录前驱 
    for(int k=0;k<max_node;k++)//更新两点间的最短路 
        for(int i=0;i<max_node;i++)
            for(int j=0;j<max_node;j++)
                if(!(G[i][k]==INF||G[k][j]==INF)&&G[i][k]+G[k][j]<G[i][j]){//加判断防止溢出 
                    G[i][j]=G[k][j]+G[i][k];
                    path[i][j]=path[k][j];//只记录前驱最后查找 
                }
}

void printPath(int to,int from)//floyd输出路径 
{     
    cout<<to;    
    while(from!=to){        
        cout<<"->"<<path[from][to];
        to=path[from][to];
    }
}

int main()
    {
    for(int i=0;i<max_node;i++)
        for(int j=0;j<max_node;j++){
            G[i][j]=INF;
            if(i==j) G[i][j]=0;//自己到自己初始化为0 
        }

    G[0][1]=4;G[0][2]=2;
    G[1][2]=1;  G[1][3]=5;
    G[2][4]=10; G[2][3]=8;
    G[3][4]=2;G[3][5]=6;
    G[4][5]=3;

    G[1][0]=4;G[2][0]=2;
    G[2][1]=1;  G[3][1]=5;
    G[4][2]=10; G[3][2]=8;
    G[4][3]=2;G[5][3]=6;
    G[5][4]=3;


    floyd();
    cout<<endl;
    printPath(3,0);

    return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值