• 最短路


    1.单源最短路径:

    问题描述:

    给定一张有向图\(G=(V,E)\)\(V\)是点集,\(E\)是边集,\(|V|=n\)\(|E|=m\),节点以\([1,n]\)之间的连续整数编号,\((x,y,z)\)表示一条从\(x\)出发,到达\(y\)的长度为\(z\)的有向边。设\(1\)号点为起点,求长度为\(n\)的数组\(dis\),其中\(dist[i]\)表示从起点\(1\)到节点\(i\)的最短路径长度。

    \(Dijkstra\)算法

    流程如下:
    \(1.\)初始化\(dis[1]=0\),其余节点的\(dis\)值为无穷大。
    \(2.\)找出一个未被标记的、\(dis[x]\)最小的节点\(x\),然后标记节点\(x\)
    \(3.\)扫描节点\(x\)的所有出边\((x,y,z)\),若\(dis[y]>dis[x]+z\),则使用\(dis[x]+z\)更新\(dis[y]\)
    \(4.\)重复上述\(2~3\)两个步骤,直到所有节点都被标记。

    该算法基于贪心思想,只适用于所有边的长度都是非负数,因为只有在这时全局最小值永远不会被更新,我们不断选择最小值去更新,最终可得到\(1\)到每个节点的最短路径长度。

    上述过程的时间复杂度是\(O(n^2)\)的,我们可以用堆进行优化,将复杂度降到\(O(nlogn)\)

    代码实例:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<map>
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=2e5+10;
    int n,m,s,cnt_edge;
    int head[maxn],dis[maxn];
    bool vis[maxn];
    inline int read()
    {
        char c=getchar();int res=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
        return res*f;
    }
    struct edge
    {
        int to,nxt,dis;
    }e[maxm<<1];
    inline void add_edge(int x,int y,int w)
    {
        e[++cnt_edge].nxt=head[x];
        head[x]=cnt_edge;
        e[cnt_edge].to=y;
        e[cnt_edge].dis=w;
    }
    #define pii pair<int,int>
    #define mkp make_pair 
    #define fir first 
    #define sec second 
    inline void dijkstra()
    {
        memset(dis,0x3f,sizeof(dis));
        priority_queue<pii>pq;
        dis[s]=0;pq.push(mkp(0,s));
        while(!pq.empty())
        {
            int x=pq.top().sec;pq.pop();
            if(vis[x])continue;
            vis[x]=1;
            for(int i=head[x];i;i=e[i].nxt)
            {
                int y=e[i].to,w=e[i].dis;
                if(dis[y]>dis[x]+w){dis[y]=dis[x]+w;pq.push(mkp(-dis[y],y));}
            }
        }
    }
    int main()
    {
        n=read(),m=read(),s=read();
        for(int i=1;i<=m;i++)
        {
            int u=read(),v=read(),w=read();
            add_edge(u,v,w);
        }
        dijkstra();
        for(int i=1;i<=n;i++)printf("%d ",dis[i]);
        return 0;
    }
    
  • 相关阅读:
    Python3学习笔记(五):列表和元组
    Python3学习笔记(四):序列
    python3学习笔记(二):Python初识
    三种存储类型比较-文件、块、对象存储(转)
    PostgreSQL copy命令使用记录
    pg_bulkload使用记录
    git clone 提示输入git@xxx的密码
    UNIX发展史(BSD,GNU,linux)(转)
    PostgreSQL基于时间点故障恢复PITR( point-in-time recovery )
    recovery.conf文件详解
  • 原文地址:https://www.cnblogs.com/nofind/p/15950871.html
Copyright © 2020-2023  润新知