• 堆优DIJ模板


    Dij:贪心思想的单源最短路,时间复杂度O(n^2)。

    Dij算法流程:

    1. d数组记录源点s到每个点的距离,若无边则设为inf,标记源点;
    2. 选出d数组中未标记的最小值,该节点记为k,并标记k为已求出最短路;
    3. 枚举每个节点(记为j),若经过k到达j的路径<d[j]且未标记,则更新d[j];
    4. 重复2、3步n次;
    5. d[v]为s-v的最短路;

    堆优Dij:即用堆优化的dij算法,时间复杂度O(nlogn);(但是据说跑起来比spfa快?求神犇解释)

    堆优Dij算法流程:

    1. q为priority_queue,优先队列记录一个二元组,分别为索引位置和数值;

      d数组记录源点s到每个点的距离,若无边则设为inf;

    2. 源点入队;
    3. 队首出队并标记队首;
    4. 遍历队首的邻接点,若可松弛,则更新该邻接点的最短路并将该节点压入优先队列;

    不知道为什么,写出来的spfa和堆优dij的唯一区别就是spfa的队列变成了dij的优先队列,也不知道这样对不对,若有错误希望大家指出。

    经测试,其实无需标记,堆优dij是照着dij模板改的,求解释。。。

    例题:Codevs2038香甜的黄油

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<queue>
     4 #include<vector>
     5 #include<cstring>
     6 using namespace std;
     7 
     8 struct edge{
     9     int to;
    10     int w;
    11     int next;
    12 };
    13 
    14 struct node{
    15     int index,value;
    16     node(){};
    17     node(int x,int y){index=x;value=y;}//构造函数
    18     friend bool operator < (node a,node b){
    19         return a.value>b.value;
    20     }//重载小于号
    21 };
    22 
    23 priority_queue<node> q;
    24 edge e[10000];
    25 int ne=0,head[1000],d[1000],a[1000],answer[1000]={0};
    26 bool b[1000];
    27 
    28 void add(int a,int b,int c){
    29     e[++ne].to=b;e[ne].w=c;e[ne].next=head[a];head[a]=ne;
    30 }
    31 
    32 void dij(int k){//k为源点编号
    33     int i,v;
    34     node u;
    35     memset(d,127,sizeof(d));
    36     memset(b,0,sizeof(b));//初始化
    37     d[k]=0;
    38     //b[k]=true;
    39     q.push(node(k,0));//构造并压入源点
    40     while(!q.empty()){
    41         u=q.top();q.pop();//弹出队首
    42         //if(b[u.index])continue;
    43         //b[u.index]=true;//标记
    44         for(i=head[u.index];i!=-1;i=e[i].next){//遍历邻接点
    45             v=e[i].to;
    46             if(u.value+e[i].w<d[v]/*&&b[v]==false*/){
    47                 d[v]=u.value+e[i].w;//松弛操作
    48                 q.push(node(v,d[v]));//压入新节点
    49             }
    50         }
    51     }
    52 }
    53 
    54 int main(){
    55     int n,p,c,ans=999999999,i,j,u,v,w;
    56     memset(head,-1,sizeof(head));
    57     memset(e,0,sizeof(e));
    58     scanf("%d%d%d",&n,&p,&c);
    59     for(i=1;i<=n;i++)scanf("%d",&a[i]);
    60     for(i=1;i<=c;i++){
    61         scanf("%d%d%d",&u,&v,&w);
    62         add(u,v,w);
    63         add(v,u,w);//连边
    64     }
    65     for(i=1;i<=p;i++){
    66         dij(i);
    67         int sum=0;
    68         for(j=1;j<=n;j++)sum+=d[a[j]];
    69         ans=min(ans,sum);
    70     }
    71     printf("%d
    ",ans);
    72 }

     

     

  • 相关阅读:
    【树状数组·进阶篇】树状数组实现平衡树(树状数组上二分)
    【$Polya$定理·应用篇】$Polya$定理的几种模型简介
    【博弈论·入门篇】$SG$函数基础入门
    关于win10安装CPC专利软件以及win10安装office2003
    部署react项目到服务器,配置nginx的伪静态
    中等 39. 组合总和 (递归,去除数组中重复的元素)
    jsonp策略,cors响应头,实现跨域
    文档-关于这次参加比赛写文档的总结
    前端-关于这次暑假的和大家一起做项目的总结
    servlet获取前台数据或者返回前台数据乱码的问题
  • 原文地址:https://www.cnblogs.com/y-m-y/p/5730794.html
Copyright © 2020-2023  润新知