zoukankan      html  css  js  c++  java
  • (学习2)Floyd和Dijkstra算法

    Floyd算法

    算法解析:因为一张连通图中不是所有点到其他点都是有一条直接路径的,所以我们可以借助别的和终点相连的点到达终点,便是起点-中转....-终点;

    以小推大,

    小:假设当前只有1可以当中转点,start为起点,end为终点;因此当start点需要借助点1到end点时,便需要进行if(edge[start][end]>edge[start][1]+edge[1][end])的判断,

    这个判断的意思就是 :我的起点到终点的路径长度是否比中转方法的长度长,这时我们当然需要优先选择短的路径,并且在edge[start][end]中更新,这样就相当于我们就确定了一条start到end的最佳路径。

    大:理解了小例子后,我们就可以去推测图上的其他所有点都可以作为某个start到某个end点的中转点,因此通过不断比较,不断更新edge[start][end],我们最后就可以得到start点到end点的最短距离矩阵。

    输入:顶点数,边数;有向图;   

    输入格式:起点 终点 路径长度;                 

    样例:4 8

    1 2 2

    1 3 6

    1 4 4

    2 3 3

    3 1 7

    3 4 1

    4 1 5

    4 3 12

    伪代码:

     1 Floyd(G){  //伪代码
     2    Edge[maxen][maxen];//有向边矩阵
     3    int n; //顶点数
     4    int m;//边数
     5    /*输入图G的顶点、边数、以及各条边的信息*/
     6    for(int k=1;k<=n;k++)
     7    for(int i=1;i<=n;i++)
     8    for(int j=1;j<=n;j++)
     9       if(Edge[i][j]>Edge[i][k]+Edge[k][j])
    10           Edge[i][j]=Edge[i][k]+Edge[k][j];
    11 }
    View Code

     源码

     1 #include <stdio.h>
     2 #include <iostream>
     3 #include <math.h>
     4 #include <algorithm>
     5 #include <string.h>
     6 using namespace std;
     7 const int maxen=200;
     8 const int Maxx=9999;
     9 int edge[maxen][maxen];
    10 void init(int n){ //初始化边矩阵
    11     for(int i=1;i<=n;i++){
    12         for(int j=1;j<=n;j++){
    13             if(i!=j)
    14               edge[i][j]=Maxx;
    15             else
    16               edge[i][j]=0;
    17         }
    18     }
    19 }
    20 void Floyd(int n){ //弗洛伊德算法
    21     for(int k=1;k<=n;k++){
    22         for(int i=1;i<=n;i++){
    23             for(int j=1;j<=n;j++){
    24                 if(edge[i][j]>edge[i][k]+edge[k][j]){
    25                     edge[i][j]=edge[i][k]+edge[k][j];
    26                 }
    27             }
    28         }
    29     }
    30 }
    31 int main(){
    32     int n,m;//n为起点,m为边数;
    33     scanf("%d %d",&n,&m);
    34     int s,e,w;        
    35     init(n);
    36     for(int i=1;i<=m;++i){
    37         scanf("%d %d %d",&s,&e,&w);
    38         edge[s][e]=w;
    39     } 
    40     Floyd(n);
    41     for(int i=1;i<=n;++i){
    42         for(int j=1;j<=n;++j){
    43             printf("s:%d e:%d w:%d
    ",i,j,edge[i][j]);//输出每条边
    44         }
    45         printf("
    ");
    46     }
    47     return 0;
    48 }
    View Code

    算法时间复杂度:O(n³)  分析:算法需要执行三个嵌套循环,所以需要n³

    Dijkstra算法

    介绍:用于计算一个节点到其他节点的最短距离的算法。

    个人算法分析  1:设两个集合A和B,A中是访问过被收纳入集合的点,B是还未访问过的点;

                            2:设一个数组visit,这个数组记录每个顶点是否被访问过;

                           3:先将起点纳入集合A,并且标记访问为true;

                           4:找出离起点最短距离的边,然后更新图中每个点到起点距离。(就是以找到的这个点为中转点,判断其他点是否能够通过这个点与起点距离拉近)

                           5:重复步骤4,直至所有点被访问过;

    时间复杂度:O(n²)

    样例           

    8 11
    1 2 1
    2 4 2
    3 1 2
    4 3 1
    4 6 8
    5 4 2
    5 7 2
    6 5 2
    7 6 3
    7 8 3
    8 6 2

    代码:

     1 #include <stdio.h>
     2 #include <iostream>
     3 #include <math.h>
     4 #include <algorithm>
     5 #include <string.h>
     6 using namespace std;
     7 const int maxen=200;
     8 const int Maxx=9999;
     9 int edge[maxen][maxen];//边矩阵 
    10 int visit[maxen];//记录被访问过的点 
    11 int lowcost[maxen];//起到到每条边的最短距离 
    12 void init(int n){  //初始化 
    13     for(int i=1;i<=n;++i){
    14         visit[i]=false;
    15         lowcost[i]=Maxx;
    16     }
    17     for(int i=1;i<=n;i++){
    18         for(int j=1;j<=n;j++){
    19             if(i!=j)
    20               edge[i][j]=99999;
    21             else
    22               edge[i][j]=0;
    23         }
    24     }
    25 }
    26 void Dijkstra(int start,int n){
    27     for(int i=1;i<=n-1;i++){  //还剩下N-1的点需要去访问 
    28         int minn=99999;
    29         int index=0;
    30         for(int j=1;j<=n;j++){
    31             if(minn>lowcost[j]&&visit[j]!=true){  //寻找与起点距离最小且还未访问的点 
    32                 minn=lowcost[j]; 
    33                 index=j;
    34             }
    35         }
    36         visit[index]=true;  //标记访问 
    37         for(int k=1;k<=n;k++){  //更新起点到其他点的距离 
    38             if(lowcost[k]>lowcost[index]+edge[index][k]){  //这里是lowcost[index]的原因是edge里面的边长不是更新过的边长 
    39                 lowcost[k]=lowcost[index]+edge[index][k];
    40             }
    41         }
    42     }
    43 }
    44 int main(void){
    45     int n,m;//顶点数与边数
    46     int s,e,w;
    47     scanf("%d %d",&n,&m);
    48     init(n);//初始化数组 
    49     for(int i=1;i<=m;i++){
    50         scanf("%d %d %d",&s,&e,&w);
    51         edge[s][e]=w;
    52         if(s==start) lowcost[e]=w;//记录当前与起点直接相连的点 
    53     } 
    54     int start=1;//起点为点1
    55     lowcost[start]=0;//起点到本身的距离为0 
    56     visit[start]=true; //起点标记已访问状态 
    57     Dijkstra(start,n); 
    58     printf("%d
    ",lowcost[8]);//输出点1到点8的距离 
    59     return 0;
    60 }
    View Code

     github:https://github.com/yizhihenpidehou/bananas/tree/master/%E7%AC%AC%E4%BA%8C%E5%91%A8

  • 相关阅读:
    IIS主机托管的FSO设置用户权限问题
    关于使用UTF8开发ASP网站
    构建Android开发环境
    iOS如何取得APP的版本信息跟服务器对比进行升级提示?
    经典讲解VB.NET线程方法之访问数据库
    IIS7.0下ASP+Access(MDB)应用环境设置要点
    一文明白数据库事务隔离级别
    EA鼻祖,Zachman,6 行(视点)+ 6 列(W5H)+ 6 条规则
    C语言位运算详解
    关于while 和if
  • 原文地址:https://www.cnblogs.com/pipihoudewo/p/12403957.html
Copyright © 2011-2022 走看看