zoukankan      html  css  js  c++  java
  • 算法竞赛模板 最短路

    ①多源最短路

    弗洛伊德算法(Floyd)

    弗洛伊德算法基本思想就是:

    (1) 最开始只允许经过1号顶点进行中转;

    (2) 接下来只允许经过1和2号顶点进行中转,以此类推;

    (3) 直到最后允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。

    算法基本思路:在只经过前k号点的前提下,更新从i号顶点到j号顶点的最短路程

    #include<bits/stdc++.h>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int M=1e3+5;
    int n,m,e[M][M];
    void init()
    {
        for(int i=1;i<=n;i++)  
            for(int j=1;j<=n;j++)  
                if(i==j) 
                    e[i][j]=0;    
                else 
                    e[i][j]=INF;  
                    
        int u,v,w;  
        for(int i=1;i<=m;i++)  
        {  
            scanf("%d%d%d",&u,&v,&w);  
            e[u][v]=w;  
        }
    }
    void floyd()
    {
        init();
        for(int k=1;k<=n;k++)  
            for(int i=1;i<=n;i++)  
                for(int j=1;j<=n;j++)  
                    if(e[i][j]>e[i][k]+e[k][j])   
                        e[i][j]=e[i][k]+e[k][j];
    }
    int main()
    {  
        cin>>n>>m;
        floyd();
        return 0;  
    } 
    floyd算法模板

    ②单源最短路

    迪杰斯特拉算法(Dijkstra)

    (1) 最基础的版本,时间复杂度O(2n2)

    dist数组:初始点到其余各个顶点的最短路径;

    vis数组:下标和dist数组对应;

    <1>若值为false,则该点为未确定点,dist数组里的对应值是未确定的;

    <2>若值为true,则该点为已确定点,dis数组里的对应值是确定的;

    算法基本思路:每次找到离源点(我们目前指定的初始点就是1号顶点)最近的一个顶点,然后以该顶点为中心进行扩展,

    不断更新源点到其余所有点的最短路径。

    #include<bits/stdc++.h>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxSize=1e3+5;
    int n,m,e[maxSize][maxSize],dist[maxSize];
    void dijkstra(int x)
    {
        int vis[maxSize],i,j,u,minn;
        for(i=1;i<=n;i++)
        {
            dist[i]=e[x][i];
            vis[i]=0;
        } 
        vis[x]=1;
        for(i=1;i<n;i++)
        {
            minn=INF; 
            for(j=1;j<=n;j++)
                if(!vis[j]&&dist[j]<minn)
                {
                    u=j;
                    minn=dist[j];
                }
            vis[u]=1;
            for(j=1;j<=n;j++)
                if(!vis[j]&&dist[j]>dist[u]+e[u][j])
                    dist[j]=dist[u]+e[u][j];        
        }
    }
    int main()
    {
        int i,j,u,v,w,x;
        while(cin>>n>>m)
        {
            for(i=1;i<=n;i++)
                for(j=1;j<=n;j++)
                    if(i==j)e[i][j]=0;  
                    else e[i][j]=INF;
            for(i=1;i<=m;i++)
               {
                scanf("%d%d%d",&u,&v,&w);
                e[u][v]=w;
            }
            cin>>x;
            dijkstra(x);
            for(i=1;i<=n;i++)
                cout<<dist[i]<<" ";
        }
        return 0;
    }
    dijkstra基础算法

    (2) 链式前向星版本,时间复杂度O(n2

    dis数组:初始点s到其余各个顶点的最短路径;

    算法基本思路:从初始点开始作为中介点u,不断加入以中介点u为起点的已存在边的终点v,如果dis[u]+这条边的权值w<dis[v],则更新dis[v]。

    #include<bits/stdc++.h>
    using namespace std;
    #define MAX 105 
    #define INF 0x3f3f3f3f
    int head[MAX],dis[MAX],cn;
    struct edge
    {
        int w,to,next;
    }e[MAX*MAX];
    void add(int u,int v,int w)
    {
        e[++cn].w=w;
        e[cn].next=head[u];
        e[cn].to=v;
        head[u]=cn; 
    } 
    void dij(int s)
    {
        int he=0,ta=0,qu[MAX*MAX],i;
        qu[ta++]=s;
        dis[s]=0;
        while(he<ta)
        {
            int u=qu[he++];
            for(i=head[u];i!=-1;i=e[i].next)
            {
                edge x=e[i];
                if(dis[x.to]>dis[u]+x.w)
                {
                    dis[x.to]=dis[u]+x.w;
                    qu[ta++]=x.to;
                }
            }
        }
    } 
    int main()
    {
        int n,m,i;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(dis,INF,sizeof(dis));
            memset(head,-1,sizeof(head));
            for(i=1;i<=m;i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,w);
            }
            int s;
            cin>>s;
            dij(s);
            for(i=1;i<=n;i++)
            cout<<dis[i]<<" ";
        }
    }
    dijkstra链式前向星版本

    (3) vector邻接表版本,时间复杂度O(n2)

    算法基本思路:与链式前向星版本同理。

    #include<bits/stdc++.h>
    using namespace std;
    #define MAX 10005
    #define INF 0x3f3f3f3f
    typedef pair<int,int> pii;
    vector<pii>vec[MAX];
    int dis[MAX];
    void dij(int s)
    {
        memset(dis,INF,sizeof(dis));
        dis[s]=0;
        int qu[MAX],he=0,ta=0,i;
        qu[ta++]=s;
        while(he<ta)
        {
            int u=qu[he++];
            for(i=0;i<vec[u].size();i++)
            {
                int v=vec[u][i].first;
                int w=vec[u][i].second;
                if(dis[v]>dis[u]+w)
                {
                    dis[v]=dis[u]+w;
                    qu[ta++]=v;
                }
            }
        }
    }
    int main()
    {
        int n,m,i;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=1;i<=m;i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                vec[u].push_back(pii(v,w));
            }
            int s;
            cin>>s;
            dij(s);
            for(i=1;i<=n;i++)
            cout<<dis[i]<<" ";
        }
        return 0;
    } 
    dijkstra邻接表版本
  • 相关阅读:
    php解析XML的两种方法
    Windows下xampp搭配php环境以及mysql的设置和php连接Mysql数据库
    管道
    Ubuntu文件系统
    Ubuntu如何使用Vscode写C++代码
    Ubuntu如何百度云盘下载
    Debug程序的使用
    寄存器
    汇编指令
    汇编第二章_寄存器
  • 原文地址:https://www.cnblogs.com/kannyi/p/8675687.html
Copyright © 2011-2022 走看看