zoukankan      html  css  js  c++  java
  • 最短路径 SPFA P3371 【模板】单源最短路径(弱化版)

    P3371 【模板】单源最短路径(弱化版)

    SPFA算法:

           SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同,为 O(VE)。

     

    SPFA和Dijkstra不同的是:

      Dijkstra  是从一个点的所有出边中找到一个最短出边,用它来继续更新下边的点

       SPFA     是用一个点的所有出边都更新它下面的点

                     更新之前把这个点存进队列

                     更新时把他拿出来,再把更新的出边终点(未入队的)入队

                     一直不断更新,直到队列为空

                     队列里存的是

     (下面有详细解释,在链式前向星以后)

    head[---]     这里大小根据点数决定
                        记录存边的历史,存的是i点的最后一条出边(它经历了不断更新)

     vis[---]         判断是否已存入队列

     dis[---]         从起点开始到当前点的最短路径

     num_edge  表示边的编号

    这里要用链式前向星存图:

    //以下为链式前向星存图 
    void addedge(int from,int to,int dis)   //存储每一条边 :起点,终点,长度
    {
        num_edge++;                         //新建一条边 
        edge[num_edge].next=head[from];     //上一条出边 
        edge[num_edge].to=to;
        edge[num_edge].dis=dis;
        head[from]=num_edge;                //记录最后一条出边 
    }

     这里edge[1]=0,因为它是顶点1的第一条出边

            edge[2]=1,edge[3]=2,

            edge[5]=0,因为它是顶点5 的第一条出边

            edge[7]=5

    SPFA

    默认起点是1

     用到1就把它弹出再用6更新5入队再用3更新

    直到队列为空

    【代码】:

    #include<bits/stdc++.h>
    #include<queue>
    using namespace std;
    
    const int inf=2147483647;
    
    int n,m,s;
    int dis[10008],vis[10008],head[10008],num_edge;
    
    struct Edge
    {
        int next,to,dis;
    }edge[500008];  //大小由边数决定
    // to   目标点
    // dis  权值
    // next 该点的上一条出边
    
    queue<int>q;
    
    //以下为链式前向星存图 
    void addedge(int from,int to,int dis) //存储每一条边 : 起点,终点,长度 { num_edge++; //新建一条边 edge[num_edge].next=head[from]; //上一条出边 edge[num_edge].to=to; edge[num_edge].dis=dis; head[from]=num_edge; //记录最后一条出边 } void spfa() { for(int i=1;i<=n;i++) { dis[i]=inf; //初始化最大值 vis[i]=0; //都不入队 } dis[s]=0; vis[s]=1; q.push(s); //把起点S入队 while(!q.empty()) { int u=q.front(); //当前起点 q.pop(); //用就弹出 vis[u]=0; //弹出后记录为不在队列 for(int i=head[u];i;i=edge[i].next) //遍历起点的所有出边 { int v=edge[i].to; //当前终点 if(dis[v]>dis[u]+edge[i].dis)
    //如果【起点到当前终点的距离】>【起点到当前起点的距离+当前距离与当前终点距离】
    //那就更新为更小距离
    { dis[v]
    =dis[u]+edge[i].dis; if(!vis[v]) //未入队的当前终点入队 { q.push(v); vis[v]=1; } } } } } int main() { scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } spfa(); for(int i=1;i<=n;i++) { if(i==s) printf("0 "); else printf("%d ",dis[i]); } return 0; }
  • 相关阅读:
    per-CPU变量
    oom killer
    System.map文件的作用
    Linux电源管理(9)_wakelocks【转】
    Linux内核的冷热缓存
    浅谈TCP IP协议栈(四)IP协议解析
    浅谈TCP IP协议栈(三)路由器简介
    CFS调度器(1)-基本原理
    浅谈TCP IP协议栈(二)IP地址
    (利用DOM)在新打开的页面点击关闭当前浏览器窗口
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/10764450.html
Copyright © 2011-2022 走看看