zoukankan      html  css  js  c++  java
  • 单源最短路dijkstra算法&&优化史

    一下午都在学最短路dijkstra算法,总算是优化到了我能达到的水平的最快水准,然后列举一下我的优化历史,顺便总结总结

    最朴素算法:

        邻接矩阵存边+贪心||dp思想,几乎纯暴力,luoguTLE+MLE,

        算优点??:但好写好想,比下面的代码短了差不多一半。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    int main()
    {
        int a[100][100],point,i,j,k,number,t1,t2,t3,u,n,min,book[10]={0},dis[10];
        int inf=99999999;
        scanf("%d %d
    ",&point,&number);
        int x;
        cin>>x; 
        for(int i=1;i<=point;i++)
          for(int j=1;j<=point;j++)
            if(i==j)a[i][j]=0;
            else
              a[i][j]=inf;
        
        for(int i=1;i<=number;i++)
        {
            cin>>t1>>t2>>t3;
            a[t1][t2]=t3;
        }
        
        for(int i=1;i<=point;i++)
          dis[i]=a[1][i];
          
        for(int i=1;i<=point-1;i++)
        {
            min=inf;
            for(int j=1;j<=point;j++)
              if(book[j]==0&& dis[j]<min)
              {
                  min=dis[j];
                  u=j;
              }
            book[u]=1;
            for(int k=1;k<=point;k++)
            {
                if(a[u][k]<inf)
                  if(dis[k]>dis[u]+a[u][k])
                    dis[k]=dis[u]+a[u][k];
            }
        }
        for(int i=1;i<=point;i++)
          cout<<i<<" "<<dis[i]<<endl;
        return 0;          
    }

    第一次优化是前向星存边,

    比上面最朴素的大量省空间,也省了部分时间,luogu上共用时1400ms+,一个点max接近五百。

     1 #include<iostream>
     2 #include <algorithm>
     3 #include <string>
     4 #include <cmath>
     5 #include <cstring>
     6 # include <cstdio> 
     7 #define maxi 2147483647;
     8 
     9 using namespace std;
    10 
    11 struct node
    12 {
    13     int z;//子节点
    14     int val;//权值
    15     int nexty;//最近父节点相同边编号 
    16 }edge[1000000];
    17 int head[20000];//某点为父节点运出的最后一条边
    18 int cnt=0,curr;// 边id
    19 
    20 inline void add(int a,int b,int c)//建立边向前星
    21 {
    22    cnt++;
    23    edge[cnt].z=b;
    24    edge[cnt].val =c;
    25    edge[cnt].nexty =head[a];
    26    head[a]=cnt;
    27 }
    28 
    29 int main()
    30 {
    31     bool visit[20001]={0};//是否已经加入最短路 
    32     long long dis[20001];//最短路存值 
    33     int n,m,s;
    34     int a,b,c;
    35     
    36     scanf("%d%d%d",&n,&m,&s);
    37     for(int i=1;i<=n;i++)//初始化边权值为无穷 
    38       dis[i]=maxi;
    39     for(int i=0;i<m;i++)
    40     {
    41         scanf("%d%d%d",&a,&b,&c);
    42         add(a,b,c);
    43     }
    44     //读入 
    45     curr=s;
    46     dis[s]=0;//到最初点距离为零 
    47     long long minn;
    48     
    49     while(!visit[curr])
    50     {
    51         visit[curr]=true;
    52         for(int i=head[curr];i!=0;i=edge[i].nexty )
    53         {
    54             if(!visit[edge[i].z]&&dis[edge[i].z]>dis[curr]+edge[i].val )
    55               dis[edge[i].z]=dis[curr]+edge[i].val;
    56         }
    57         minn=2147483647;
    58         for (int i=1;i<=n;i++)
    59           if(!visit[i]&&minn>dis[i])
    60           {
    61               minn=dis[i];
    62               curr=i;
    63           }
    64     }
    65     for (int i=1;i<=n;i++)
    66       printf("%lld ",dis[i]);
    67     return 0;
    68 }
    dijkstra优化1

    最后的优化使代码长达近百行

    主要运用:快读快写,优先队列(堆),前向星存边

    不过这次优化使用结构体存边的时候发生了玄学错误,现在还是找不出错,不过用几个数组存边就AC了???

    个人是喜欢结构体的,毕竟好写也整齐,但是没通过的话就不发出来了

    这个复杂度又比上一个程序降低了不少,luogu 共用时500+ms,单个点max160+ms,比上一个快了大概3,4倍

    下面这个是ac的数组存边。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <queue>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <stdio.h>
     7 #include <string.h>
     8 #define maxn 10005
     9 #define maxm 500005
    10 #define inf 2147483647
    11 
    12 using namespace std;
    13 
    14 int n,m,cnt=0;
    15 bool visit[maxn];
    16 int head[maxm],next[maxm],v[maxm],w[maxm],dist[maxn];
    17 
    18 inline int read()  
    19 {  
    20     char ch;  
    21     int a=0;  
    22     while(!(((ch=getchar())>='0')&&(ch<='9')));  
    23     a*=10;a+=ch-'0';  
    24     while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';  
    25     return a;  
    26 }
    27 
    28 void write(int x)
    29 {
    30     if(x<0) putchar('-'),x=-x;
    31     if(x>9)write(x/10);
    32     putchar(x%10+'0');
    33     return ;
    34 }
    35 
    36 struct cmp
    37 {
    38     bool operator()(int x,int y)
    39     {
    40         return dist[x]>dist[y];
    41     }
    42 };
    43 
    44 void add(int a,int b,int c)
    45 {
    46     v[cnt]=b;
    47     w[cnt]=c;
    48     next[cnt]=head[a];
    49     head[a]=cnt++;
    50     return ;
    51 }
    52 
    53 void dijk(int s)
    54 {
    55     priority_queue<int,vector<int>,cmp> q2;
    56     while(!q2.empty() )
    57       q2.pop() ;
    58     dist[s]=0;
    59     q2.push(s);
    60     while(!q2.empty() )
    61     {
    62         int x=q2.top() ;
    63         q2.pop() ;
    64         if(!visit[x])
    65         {
    66             visit[x]=true;
    67             for(int i=head[x];i!=-1;i=next[i])
    68             {
    69                 int y=v[i];
    70                 dist[y]=min(dist[y],dist[x]+w[i]);
    71                 q2.push(y);
    72             }
    73         }
    74     }
    75     return ;
    76 }
    77 
    78 int main()
    79 {
    80     int s;
    81     n=read();
    82     m=read();
    83     s=read();
    84     memset(head,-1,sizeof(head));
    85     memset(visit,0,sizeof(visit));
    86     for(int i=1;i<=m;i++)
    87     {
    88         int a,b,c;
    89         a=read(),b=read(),c=read();
    90         add(a,b,c);
    91     }
    92     for(int i=1;i<=n;i++)
    93       dist[i]=inf;
    94     dijk(s);
    95     for(int i=1;i<=n;i++)
    96       write(dist[i]),putchar(' ');
    97     return 0;
    98 }
    dijkstra优化2

    注意!这不是最优化dijkstra,只是个人能力能达到的最优化了。。。

    写那么长的代码还是挺有成就感的

    ———————————————————————————————— 执笔饰年华,一笑叹天涯。逢春即润物,生当得潇洒。
  • 相关阅读:
    Docker
    Dotted lines by default in ViVA
    8245H(C2)光猫配置方法
    两种将verilog网表转为spice网表的方法
    calibredrv create reference cell
    怎么flatten一个GDS所有层次
    路由器后面访问光猫
    贝尔IPTV
    PDK导出的cdl MOS四端顺序不正确
    如何删除已经存在lib的techfile
  • 原文地址:https://www.cnblogs.com/SuperGoodGame/p/9052990.html
Copyright © 2011-2022 走看看