zoukankan      html  css  js  c++  java
  • 图论之最短路算法之SPFA算法

    SPFA(Shortest Path Faster Algorithm)算法,是一种求最短路的算法。

    SPFA的思路及写法和BFS有相同的地方,我就举一道例题(洛谷——P3371 【模板】单源最短路径(弱化版)来做讲解吧!

    如题:
    在这里插入图片描述
    首先,我们先来定义一波变量吧:

    struct node{
    	int v,w;
    	node (){ }
    	node (int _v,int _w){
    		v=_v;
    		w=_w;
    	}//构造函数
    };
    
    queue<int>qu;//必备队列
    
    const int inf=0x3f3f3f3f;//最大值
    
    vector<node> g[10010];//动态数组存点集
    int inq[10010],dst[10010];//标记数组以及确认的最短路经
    int n,m;
    

    然后再来一个存图函数

    void add(int u,int v,int w){
    	g[u].push_back(node(v,w));
    }
    

    好了,基本的变量函数已经准备好了,现在就开始我们的SPFA。
    但需要传什么参数进去呢?那就简洁点,就只要一个s(松弛的点)

    void spfa(){
    
    }
    

    首先我们来给dst赋一个最大值,因为求最短路嘛,当然要赋一个最大值嘛。

    memset(dst,inf,sizeof dst);
    

    然后就标记+dst还原成0+放进队列

    int u=s;
    dst[u]=0;
    inq[u]=1;
    qu.push(u);
    

    下面就开始一波日常的操作:

    while (!qu.empty()){
    		u=qu.front();
    		qu.pop();//弹出去,不然就出不去了(无限循环)
    		inq[u]=0;//取消标记,万一会重复走呢?
    		for (int i=0;i<g[u].size();i++){
    			int v=g[u][i].v;
    			int w=g[u][i].w;//取出来,简洁
    			if (dst[v]>dst[u]+w){
    				dst[v]=dst[u]+w;//如果松弛了更小,那就松弛吧
    				if (!inq[v]){
    					qu.push(v);
    					inq[v]=1;//如果没走过,那就放进qu在标记一下
    				}
    			}
    		}
    	}
    

    main函数里就不用讲了嘛:

    int main(){
    	int s; 
    	cin>>n>>m>>s;
    	while (m--){
    		int u,v,w;
    		cin>>u>>v>>w;
    		add(u,v,w);
    	}
    	spfa(s);
    	for (int i=1;i<=n;i++){
    		if(dst[i]==0x3f3f3f3f){
    			cout<<2147483647<<" ";
    		}else{
    			cout<<dst[i]<<" ";
    		}
    	}
    	return 0;
    }
    

    最后,完整的代码为:

    #include <bits/stdc++.h>
    using namespace std;
    struct node{
    	int v,w;
    	node (){ }
    	node (int _v,int _w){
    		v=_v;
    		w=_w;
    	}
    };
    
    queue<int>qu;
    
    const int inf=0x3f3f3f3f;
    
    vector<node> g[10010];
    int inq[10010],dst[10010];
    int n,m;
    
    void add(int u,int v,int w){
    	g[u].push_back(node(v,w));
    }
    
    void spfa(int s){
    	memset(dst,inf,sizeof dst);
    	int u=s;
    	dst[u]=0;
    	inq[u]=1;
    	qu.push(u);
    	while (!qu.empty()){
    		u=qu.front();
    		qu.pop();
    		inq[u]=0;
    		for (int i=0;i<g[u].size();i++){
    			int v=g[u][i].v;
    			int w=g[u][i].w;
    			if (dst[v]>dst[u]+w){
    				dst[v]=dst[u]+w;
    				if (!inq[v]){
    					qu.push(v);
    					inq[v]=1;
    				}
    			}
    		}
    	}
    }
    
    
    int main(){
    	int s; 
    	cin>>n>>m>>s;
    	while (m--){
    		int u,v,w;
    		cin>>u>>v>>w;
    		add(u,v,w);
    	}
    	spfa(s);
    	for (int i=1;i<=n;i++){
    		if(dst[i]==0x3f3f3f3f){
    			cout<<2147483647<<" ";
    		}else{
    			cout<<dst[i]<<" ";
    		}
    	}
    	return 0;
    }
    

    完美结束

  • 相关阅读:
    【文字检测算法整理】
    【LDA】周志华
    【PCA】周志华
    【SVM】周志华
    4.1、顺序栈的实现(java实现)
    3.1、双向循环链表(java实现)
    5、链表队列(java实现)
    4、链栈的实现(java代码)
    3、循环链表(java实现)
    CommonsMultipartFile 转为 File 类型
  • 原文地址:https://www.cnblogs.com/herobrine-life/p/10959549.html
Copyright © 2011-2022 走看看