单源最短路径

单源最短路径算法,其实就是进行松驰的算法。
有Dijkstra/Bellman ford/SPFA 这三种算法
如图所示:

算法模板:
共用代码

#define NMAX 105
#define EMAX 10005
int head[NMAX];
int dist[NMAX];
int ver[EMAX];
int nxt[EMAX];
int wi[EMAX];
int tot;

void add(int u,int v,int w){
	ver[++tot] = v;
	nxt[tot] = head[u];
	head[u] = tot;
	wi[tot] = w;
}

bool relax(int u,int v,int w){
	if ( dist[v] > dist[u] + w ){
		dist[v] = dist[u] + w;
		return true;
	}
	return false;
}

void reset(){
	memset(ver,0,sizeof(ver));
	memset(head,0,sizeof(head));
	memset(wi,0,sizeof(wi));
	memset(nxt,0,sizeof(nxt));
	tot = 0;
}

Bellman ford

int bellmanford(int n,int source,int target){
	dist[source] = 0;
	for( int i=1;i<n;i++ ){
		bool flag = false;//tle解决方案
		for(int u=1;u<=n;++u){
			for( int e=head[u];e>0;e=nxt[e] ){
				int v = ver[e];
				int w = wi[e];
				flag = relax(u,v,w) || flag;
			}
		}
		if ( !flag ) break;
	}
	return dist[target];
}

spfa

int spfa(int n,int source,int to){
    memset(bv,0,sizeof(bv));
    dist[source] = 0;
    list<int> li;
    li.push_back(source);
    //bv是用来判断是否在队列中的
    //并不是  是否已经被访问过。这点与dijkstra不同
    bv[source] = true;
    while(!li.empty()){
        int u = li.front();
        li.pop_front();
        bv[u] = false;
        for(int e=head[u];e;e=nxt[e]){
            int v = ver[e];
            if(dist[v]>dist[u] + wi[e]){
                dist[v] =dist[u] + wi[e];
                if ( !bv[v]){
                    li.push_back(v);
                    bv[v] = true;
                }
            }
        }
    }
    return dist[to];
}

Dijkstra

int dijkstra(int n,int source,int to){
	memset(bv,0,sizeof(bv));
	dist[source] = 0;
	priority_queue<pair<int,int>> q;
	q.push(pair<int,int>(0,source));
	while(!q.empty()){
		int u = q.top().second;
		q.pop();
		if ( bv[u]) continue;
		bv[u] = true;
		for( int e=head[u];e>0;e=nxt[e]){
			int v = ver[e];
			if ( dist[v] > dist[u] + wi[e]) {
				dist[v] = dist[u] + wi[e];
				q.push(pair<int,int>(-dist[v],v));
			}
		}
	}
	return dist[to];
}
posted @ 2022-05-30 10:47  传说中的水牛  阅读(45)  评论(0编辑  收藏  举报