最短路经问题

Prim算法:

主要处理问题:最小生成树问题。

算法思想:V表示所有节点集合,首先s进入集合U,然后找出集合U与剩余节点V-U中最小权值的边[u,v],将v加入集合U,直到U==V截至

时间复杂度:相对与Kruskal需要多次排序,>>O(E)

Kruskal算法:推荐

主要处理问题:最小生成树问题。

算法思想:对所有边按照权值进行排序,然后使用并查集,将所有节点加入到集合中。

时间复杂度:O(E)

Dijkstra算法:推荐

主要处理问题:权值为正,单源点最短路径问题

算法思想:N-1次松弛,每次找出没有被访问过d值最小的节点x,然后对所有与x相连的节点进行松弛

时间复杂度:O(N*N),比较稳定

Bellman_Ford算法:

主要处理问题:权值为负,无负环,单源点最短路径问题

算法思想:N-1次松弛,每次历遍完所有边进行松弛

时间复杂度:O(N*E)

SPFA算法:推荐

(Shortest Path Faster Algorithm)

主要处理问题:权值为负,无负环,单源点最短路径问题。或者稀疏图,邻接表实现

算法思想:bfs+松弛,队实现,首先s入队,输出队首元素u,然后历遍与u相连的所有边[u,v],然后进行松弛,如果松弛成功,并且v没有在队中,则将v入队。

时间复杂度:O(E) --- O(N*E),不稳定

拓展:如果某一个节点入队超过N-1次,则存在负环

Floyd算法:

主要处理问题:所有节点间最短路径问题
算法思想:动态规划,三重循环
时间复杂度:O(N^3)

算法模板:

//Dijkstra
int dijkstra(int s, int e)
{
	for(i = 0; i < N; ++ i) d[i] = INF;
	d[s] = 0;
	memset(vis, 0, sizeof(vis));
	for(i = 0; i < N - 1; ++ i)
	{
		int x = 0;
		for(j = 0; j <= N; ++ j) if(!vis[j] && d[j] < d[x]) 
			x = j;
		vis[x] = 1;
		for(j = 0; j <= N; ++ j) if(map[x][j] && d[j] > d[x] + map[x][j]) 
			d[j] = d[x] + map[x][j];
	}
	return d[e];
}

//SPFA
struct Node
{
	int v, w;
};
vector G[nMax];
int vis[nMax];
int spfa(int s, int e)
{
	memset(vis, 0, sizeof(vis));
	for(i = 0; i < N; ++ i) dis[i] = INF;
	dis[s] = 0;
	queue que;
	que.push(s);
	while(!que.empty())
	{
		int u = que.front();
		que.pop();
		vis[u] = 0;
		for(i = 0; i < G[u].size(); ++ i)
		{
			Node tmp = G[u][i];
			if(dis[tmp.y] > dis[u] + tmp.w)
			{
				dis[tmp.y] = dis[u] + tmp.w;
				if(!vis[tmp.y])
				{
					vis[tmp.y] = 1;
					que.push(tmp.y);
				}
			}
		}
	}
	return dis[e];
}

//Floyd
for(k = 0; k < N; ++ k)
for(i = 0; i < N; ++ i)
for(j = 0; j < N; ++ j)
if(d[i][j] > d[i][k] + d[k][j])
d[i][j] = d[i][k] + d[k][j];


推荐博客: http://blog.csdn.net/v_JULY_v/article/details/6181485

你可能感兴趣的:(算法总结)