BF
Dijkstra算法可以很好的解决无负权图,但如果出现了负权边,便会失效。
首先,图的任意一条最短路径既不能包含负权回路,也不会包含正权回路,因此它最多包含|v|-1条边。,如果把源点S作为一棵树的根结点,把其他结点按照最短路径的结点顺序连接,就会生成一棵最短路径树。
主要思路如下(伪代码)复杂度为(V*E):
1 2 3 4 5 6 7 8 9 10
| for(i=0;i<n-1;i++) { for(each edge u->v) { if(d[u]+length[u->v]<d[v]) { d[v]=d[u]+length[u->v]; } } }
|
邻接表的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| struct node { int v,dis; };
vector<node> aj[maxx]; int n; int d[maxx];
bool bellman(int s) { fill(d,d+maxx,INF); d[s]=0; for(int i=0;i<n-1;i++) for(int u=0;u<n;u++) for(int j=0;j<aj[u].size();u++) { int v=aj[u][j].v; int dis=aj[u][j].dis; if(d[u]+dis<d[v]) d[v]=d[u]+dis; } for(int u=0;u<n;u++) for(int j=0;j<aj[u].size();j++) { int v=aj[u][j].v; int dis=aj[u][j].dis; if(d[u]+dis<d[v]) { return false; } } return true; }
|
SPFA
Bellman-Ford算法时间复杂度过高,优化后被称为SPFA算法。
代码思路如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| struct node { int v,dis; };
vector<node> aj[maxx]; int n; int d[maxx]; bool inq[maxx];
bool SPFA(int s) { memset(inq,false,sizeof(inq)); memset(num,0,sizeof(num)); fill(d,d+maxx,INF); queue<int> q; q.push(s); inq[s]=true; num[s]++; d[s]=0; while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=false; for(int j=0;j<aj[u].size();j++) { int v=aj[u][j].v; int dis=aj[u][j].dis; if(d[u]+dis<d[v]) { d[v]=d[u]+dis; if(!inq[v]) { q.push(v); inq[v]=true; num[v]++; if(num[v]>=n) return false; } } } } return true; }
|