SPFA算法模板(C/C++)

单源最短路径算法,可以用于解决带负边权的情况。是队列优化的Bellman-Ford算法,时间复杂度O(nm)。

朴素spfa算法模板

#include 
#include 

const int N = 1010, M = 2e6, INF = 1e9;

int n, m;	//n是节点数,m是边数
int dist[N], q[N];	//dist[i]表示源点到i点的最短距离
int h[N], to[M], w[M], ne[M], idx;	//idx初始化为0
bool st[N];	//储存每个点是否在队列中

//添加边表示a到b有一条单向边,权值为c
void add(int a, int b, int c){
     
    to[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

//求源点s到其它点的最短路径
void spfa(int s){
     
    int hh, tt;	//队列头指针和尾指针
    memset(st, false, sizeof(st));
    for(int i = 1; i <= n; i++) dist[i] = INF;
   	dist[s] = 0;
    q[tt++] = s;
    st[s] = true;
    while(hh != tt){
     	//队列不为空
        int t = q[hh++];
        st[t] = false;
        if(hh == N) hh = 0;
        for(int i = h[i]; ~i; i = ne[i]){
     
            if(dist[t] + w[i] < dist[to[i]]){
     
                dist[to[i]] = dist[t] + w[i];
                if(!st[to[i]]){
     
                    st[to[i]] = true;
                    q[tt++] = to[i];
                    if(tt == N) tt = 0;
                	}
            	}
        	}
    	}
}

int main(void){
     
    int a, b, c;
    scanf("%d %d %d", &n, &m, &s);
    memset(h, -1, sizeof(h));
    for(int i = 1; i <= m; i++){
     
        scanf("%d %d %d", &a, &b, &c);
        add(a, b, c);
    	}
   	spfa(s);
    for(int i = 1; i <= n; i++){
     
        if(dist[i] == INF) puts("NO PATH");
        else printf("%d\n", dist[i]);
    	}
   	return 0;
}

SLF优化的SPFA算法

SLF 优化:将普通队列换成双端队列,每次将入队结点距离和队首比较,如果更大则插入至队尾,否则插入队首

#include 
#include 
#include 
using namespace std;

const int N = 1010, M = 2e6, INF = 1e9;

int dist[N];
int h[N], to[M], w[M], ne[M], idx;
bool st[N];
int n, m;

void add(int a, int b, int c){
    to[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

void spfa(int s){
    memset(st, false, sizeof(st));
    for(int i = 1; i <= n; i++) dist[i] = INF;
    dist[s] = 0;
    deque q;
    q.push_front(s);
    st[s] = true;
    while(!q.empty()){
        int t = q.front();
        q.pop_front();
        st[t] = false;
        for(int i = h[t]; ~i; i = ne[i]){
            if(dist[t] + w[i] < dist[to[i]]){
                dist[to[i]] = dist[t] + w[i];
                if(!st[to[i]]){
                    if(!q.empty() && dist[to[i]] < dist[q.front()]){
                        q.push_front(to[i]);
                    	}
                    else q.push_back(to[i]);
                    st[to[i]] = true;
                	}
            	}
        	}
    	}
}

你可能感兴趣的:(图论,队列,算法,c++,数据结构,图论)