• 最短路总结


    第一种:floyd_warshall

      简单点说就是三重FOR循环  

      从 一点到另一点  寻找他们中间能否一有点作为媒介使得他们的权值(距离)更小

      如果有就更新他们的距离(权值);

      而中间媒介点靠的就是最外层的FOR循环

      附上源码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define inf 0x3f3f3f3f
    #define mnum 1000
    #define mm(a,b) memset(a,b,sizeof(a))
    using namespace std;
    int n,m,map[mnum][mnum];
    floyd_warshall()//弗洛伊德 
    {
        for(int k=1; k<=n; k++)//中间边(媒介)遍历
            for(int i=1; i<=n; i++)//
                for(int j=1; j<=n; j++)
                    if(map[i][k]!=inf&&map[k][j]!=inf
                            &&map[i][j]>map[i][k]+map[k][j])
                        map[i][j]=map[i][k]+map[k][j]
                    }
    int main()
    {
        int first,last;
        while(cin>>n>>m>>fist>>last)
        {
            mm(map,inf);
            for(int i=1; i<=n; i++)
                map[i][i]=0;
            while(m--)
            {
                int u,v,w;
                cin>>u>>v>>map[u][v];
            }
            floyd_warshall()
            cout<<map[first][last]<<endl;
        }
        return 0;
    }

    第二种:dijkstra

    其时和弗洛伊德算法差不多都是找媒介点更新距离(权值)

    只不过他有一个查找距离起始点最近的然后更新对应的(松弛)

    而且比弗洛伊德的优势是他能够便捷的求出 终点到各点的值

    对于来回问题比较容易求解

    附上源码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define maxx 1005
    #define inf 0x3f3f3f3f//自定义最大值 
    #define mem(a,b) memset(a,b,sizeof(a))
    //重新定义 初始化函数  
    using namespace std;
    int n,m,fid,dis[maxx],vis[maxx],map[maxx][maxx],total[maxx];
    void dijkstra(int fir)
    {
        mem(dis,0x3f);
        mem(vis,0);
        dis[fir]=0;
        for(int i=1; i<=n; i++)
        {
            int minn=inf,k;
            for(int j=1; j<=n; j++)//寻找距离源/次源点最近的点
                if(!vis[j]&&dis[j]<minn)
                {
                    k=j;
                    minn=dis[j];
                }
            vis[k]=1;
            for(int j=1; j<=n; j++)
            {
                if(dis[j]>minn+map[k][j])//源点到各点(松弛)
                    dis[j]=minn+map[k][j];
            }
        }
    }
    void dijkstraa(int fir)
    {
        mem(dis,0x3f);
        mem(vis,0);
        dis[fir]=0;
        for(int i=1; i<=n; i++)
        {
            int minn=inf,k;
            for(int j=1; j<=n; j++)//寻找到源/次源点最近
                if(!vis[j]&&dis[j]<minn)
                {
                    k=j;
                    minn=dis[j];
                }
            vis[k]=1;
            for(int j=1; j<=n; j++)
            {
                if(dis[j]>minn+map[j][k])//各点到源点(松弛)
                    dis[j]=minn+map[j][k];
            }
        }
    }
    int main()
    {
        cin>>n>>m>>fid;
        mem(map,0x3f);//快速赋值(字节赋值) 
        for(int i=0; i<m; i++)
        {
            int a,b,c;
            cin>>a>>b>>c;
            map[a][b]=c;
        }
        dijkstra(fid);//传递源点
        for(int i=1; i<=n; i++)
            total[i]=dis[i];
        dijkstraa(fid);//传递源点
        int minn=0;
        for(int i=1; i<=n; i++)
        {
            int c=total[i]+dis[i];
            if(c>minn)
                minn=c;
        }
        cout<<minn<<endl;
        return 0;
    }

    第三种:bellman_ford

    其时原理都不尽相同

    n-1次遍历不断更新(松弛)

    源码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define inf 0x3f3f3f3f
     5 #define nan -inf
     6 #define scale 105//规模 scale 
     7 #define mem(a,b) memset(a,b,sizeof(a))
     8 using namespace std;
     9 
    10 int n,m,dis[scale];
    11 
    12 struct node
    13 {
    14     int u,v,w;
    15 } p[scale];
    16 
    17 void bellman_ford(int origin)
    18 {
    19     dis[origin]=0;
    20     for(int k=1; k<n; k++) //n-1次遍历
    21         for(int i=0; i<m; i++)
    22         {
    23             //这里是双向的要一起判断 否则就凉凉
    24             if(dis[p[i].u]>dis[p[i].v]+p[i].w)
    25                 dis[p[i].u]=dis[p[i].v]+p[i].w;
    26             if(dis[p[i].v]>dis[p[i].u]+p[i].w)
    27                 dis[p[i].v]=dis[p[i].u]+p[i].w;
    28         }
    29 
    30 }
    31 int main()
    32 {
    33     int origin,terminus;
    34     while(cin>>n>>m>>origin>>terminus)//起点终点
    35     {
    36         mem(dis,inf);
    37         for(int i=0; i<m; i++)
    38         {
    39             cin>>p[i].u>>p[i].v>>p[i].w;
    40         }
    41         bellman_ford(origin);
    42         cout<<dis[terminus]<<endl;
    43     }
    44     return 0;
    45 }

    关于dijkstra的优化,SPFA后期会加上

  • 相关阅读:
    中小企业需要企业邮箱吗?中小性公司选什么邮箱性价比高?
    主流电子邮箱有哪些?你的邮箱选对了吗?
    外贸邮箱选择什么企业邮箱更安全?
    企业邮箱适用于哪些行业?公司邮箱都用什么?
    如何注册公司收费邮箱?注册公司邮箱有哪些优势?
    convert_cyr_string — 将字符由一种 Cyrillic 字符转换成另一种
    chunk_split — 将字符串分割成小块
    addslashes — 使用反斜线引用字符串
    addcslashes — 以 C 语言风格使用反斜线转义字符串中的字符
    extract — 从数组中将变量导入到当前的符号表
  • 原文地址:https://www.cnblogs.com/maxv/p/10706394.html
Copyright © 2020-2023  润新知