最短路总结:Dijkstra,SFPA,Bellman Ford判负环,Floyd

来源:互联网 发布:文华财经模拟软件 编辑:程序博客网 时间:2024/06/07 02:56

Dijkstra:(只能处理非负的)

贪心思想:

1、找到最短距离已经确定的顶点,从它出发更新相邻顶点的最短距离。

2、此后不需要再关心1中的“最短距离已确定的顶点”。

优先队列优化:

在队列中取出d值最小的结点x,然后从x出发更新所有的边的d值。

初始化:

first[u]  结点u的第一条边

next[i] 边i的下一条边

d -> INF

时间复杂度O(elogv)


#include <iostream>#include <cstring>#include <queue>#include <vector>#include <functional>using namespace std;//距离,边序号 typedef pair<int ,int> P;priority_queue<P, vector<P>, greater<P> >que;const int MAX_N = 10000, MAX_M = 10000;int d[MAX_N];struct E{int u, v, w;}e[MAX_M];int first[MAX_N], next[MAX_M];void Dijkstra(int s){//初始化,距离数组d,队列 memset(d, 0x3f, sizeof(d));d[s] = 0;que.push(P(d[s], s));while(que.size()){P x = que.top(); que.pop();//取出int u = x.second;if(x.first != d[u])//已经算过了,跳过 continue;  for(int i = first[u]; i != -1; i = next[i])if(d[u] + e[i].w < d[e[i].v]){d[e[i].v] = d[u] + e[i].w;que.push(P(d[e[i].v], e[i].v));}}}int main(int argc, char *argv[]){memset(first, -1, sizeof(first));int n, m;scanf("%d%d", &n, &m);for(int i = 0; i < m; i++){scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);next[i] = first[e[i].u];first[e[i].u] = i;}Dijkstra(e[0].u);printf("%d\n", d[5]);return 0;}


SPFA算法 负环最短路(用队列优化对Bellman Ford算法的优化):

时间复杂度:O(ke)。

初始化:

first[u]  结点u的第一条边

next[i] 边i的下一条边

d -> INF


bool inq[MAX_N];void SPFA(int s){//初始化距离d,队列,inq队列标志 queue<int> que;memset(d, 0x3f, sizeof(d));d[s] = 0;memset(inq, 0, sizeof(inq));que.push(s);while(que.size()){int u = que.front();que.pop();//清除标志 inq[u] = false;//对每一条邻边松弛操作 for(int i = first[u]; i != -1; i = next[i]) if(d[e[i].u] + e[i].w < d[e[i].v]){d[e[i].v] = d[e[i].u] + e[i].w;if(!inq[e[i].v]){inq[e[i].v] = true;que.push(e[i].v);}}}}

Bellman Ford算法判断是否存在负环:

若循环执行了n-1次,则存在负环。

注:d初始化为0即可


bool find_negative_loop(){memset(d, 0, sizeof(d));for(int i = 0; i < n; i++)for(int j = 0; j < m; j++){int u = e[j].u, v = e[j].v, w = e[j].w;if(d[u] + w < d[v]){d[v] = d[u] + w;if(i == n-1)return true;}}return false;} 

Floyd-Warshall任意两点最短路算法:

动态规划的思想:

d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

时间复杂度O(v^3)。

初始化:

d[][] -> INF

d[i][i] = 0;

d[u][v] = w;


void Floyd(){for(int k = 0; k < n; k++)for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)d[i][j] = min(d[i][j], d[i][k] + d[k][j]);}



测试:

#include <iostream>#include <cstring>#include <queue>#include <vector>#include <functional>using namespace std;int n, m;//dist, utypedef pair<int, int> P;priority_queue<P, vector<P>, greater<P> >que;  const int MAX_N = 10000, MAX_M = 10000;int d[MAX_N];//distantstruct E{int u, v, w;}e[MAX_M];int first[MAX_N], nexte[MAX_M];void Dijkstra(int s){memset(d, 0x3f, sizeof(d));d[s] = 0;que.push(P(d[s], s));  while(que.size()){P x = que.top(); que.pop();int u = x.second;//uif(x.first != d[u])//calc~edcontinue;for(int i = first[u]; i != -1; i = nexte[i])if(d[u] + e[i].w < d[e[i].v]){d[e[i].v] = d[u] + e[i].w;que.push(P(d[e[i].v], e[i].v));}}}bool inq[MAX_N];void SPFA(int s){//initqueue<int> que;memset(d, 0x3f, sizeof(d));d[s] = 0;memset(inq, 0, sizeof(inq));que.push(s);while(que.size()){int u = que.front(); que.pop();//clear flaginq[u] = false;//relaxfor(int i = first[u]; i != -1; i = nexte[i])if(d[e[i].u] + e[i].w < d[e[i].v]){d[e[i].v] = d[e[i].u] + e[i].w;if(!inq[e[i].v]){inq[e[i].v] = true;que.push(e[i].v);}}}}int dist[MAX_N][MAX_N];void Floyd(){for(int k = 0; k < n; k++)for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);}int main(){freopen("in.txt", "r", stdin);memset(first, -1, sizeof(first));//Floydmemset(dist, 0x3f, sizeof(dist));for(int i = 0; i < n; i++)dist[i][i] = 0;scanf("%d%d", &n, &m);for(int i = 0; i < m; i++){scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);nexte[i] = first[e[i].u];first[e[i].u] = i;//Floyddist[e[i].u][e[i].v] = e[i].w;}Dijkstra(e[0].u);printf("%d to %d dist = %d\n", e[0].u, n-1, d[n-1]);SPFA(e[0].u);printf("%d to %d dist = %d\n", e[0].u, n-1, d[n-1]);Floyd();printf("%d to %d dist = %d\n", e[0].u, n-1, dist[e[0].u][n-1]);for(int i = 0; i < n; i++)for(int j = 0; j < n; j++){if(dist[i][j] == 0x3f3f3f3f)printf("INF");elseprintf("%3d", dist[i][j]);printf(j == n-1 ? "\n" : " ");}return 0;}/************************************************************************//* input:6 8  0 2 10  0 4 30  0 5 100  1 2 5  2 3 50  3 5 10  4 3 20  4 5 60                                                                       *//************************************************************************/


0 0
原创粉丝点击