关于spfa的初步探究


/*
对于菜鸟,第一次接触这种大型算法,应该抽出一大段时间研究,研究这个算法我认为要有DIJ和Floyd的铺垫。
搜集各路资料,大概有以下几个要点。

1.SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。
(啊,亲,什么是Bellman-Ford?大致:1对每条边进行|V|-1次Relax操作;2如果存在(u,v)∈E使得dis[u]+w<dis[v],
则存在负权回路;否则dis[v]即为s到v的最短距离,pre[v]为前驱。)

2.算法大致流程是用一个队列来进行维护。 初始时将源加入队列。 每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,则将其入队。 直到队列为空时算法结束(很重要啊亲,对于我这样编码能力很渣的很重要,重要在什么?关键词"队列""相连")。

3.伪代码
Procedure SPFA;
 
Begin
  initialize-single-source(G,s);
  initialize-queue(Q);
  enqueue(Q,s);
  while not empty(Q) do 
    begin
      u:=dequeue(Q);
      for each v∈adj[u] do 
        begin
          tmp:=d[v];
          relax(u,v);
          if (tmp<>d[v]) and (not v in Q) then
            enqueue(Q,v);
        end;
    end;
End;
4.我代码能力渣,SPFA算法有两个优化算法 SLF 和 LLL: SLF,不会。

Autor:ray007great
*/






















/*
构图有2种,邻接矩阵版.最裸的最短路,对应hdu 2544
*/
#include 
  
  
   
   
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
        #include 
       
         #define N 150 #define inf 999999 using namespace std; queue 
        
          q; int n; int vis[N],dis[N],map[N][N]; int spfa() { int i; memset(vis,0,sizeof(vis)); for(i=0;i<=n;i++) dis[i]=inf; q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()) { int cur=q.front(); q.pop(); for(i=1;i<=n;i++) { if(map[cur][i]!=inf) { if(dis[i]>dis[cur]+map[cur][i]) { dis[i]=dis[cur]+map[cur][i]; //pre[i]=cur; if(!vis[i]) { vis[i]=1; q.push(i); } } } } vis[cur]=0; } return dis[n]; } int main() { int i,a,b,c,j,m; while(scanf("%d%d",&n,&m)!=EOF &&n&&m) { for(i=0;i<=n;i++) for(j=0;j<=n;j++) map[i][j]=inf; for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); if(map[a][b]>c) map[a][b]=map[b][a]=c; } int max=spfa(); printf("%d\n",max); } return 0; } /* 邻接矩阵版。附:邻接矩阵不用考虑重边。 */ #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #define N 150 #define inf 999999 using namespace std; struct node { int from,to,value; }; queue 
               
                 q; vector 
                
                  g[N]; int n; int vis[N],dis[N]; int spfa() { int i; memset(vis,0,sizeof(vis)); for(i=0;i<=n;i++) dis[i]=inf; q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()) { int cur=q.front(); q.pop(); for(i=0;i 
                 
                   dis[cur]+g[cur][i].value) { dis[k]=dis[cur]+g[cur][i].value; if(!vis[k]) { vis[k]=1; q.push(k); } } } vis[cur]=0; } return dis[n]; } int main() { int i,a,b,c,j,m; while(scanf("%d%d",&n,&m)!=EOF &&n&&m) { for(i=0;i<N;i++) g[i].clear(); for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); node e; e.from=a; e.to=b; e.value=c; g[e.from].push_back(e); e.from=b; e.to=a; g[e.from].push_back(e); } int max=spfa(); printf("%d\n",max); } return 0; }    
                  
                 
                
               
              
             
            
           
          
         
        
      
     
     
    
    
   
   
  
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值