Floyed算法,复杂度o(n^3);
更新i->j的距离,通过中介点k,如果能够通过k使得i->j的距离更短,那么更新。
代码
void Folyed() {
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j && i != k && j != k && d[i][j] > d[i][k] + d[k][j]) {
d[i][j] = d[i][k] + d[k][j];
}
}
}
}
}
Dijkstra算法,普通复杂度O(n^2),堆优化O(nlgn)
有个集合s,和原始图G,一个最短距离数组d。从起点开始,每次添加一个u,如果能够从中介点u更新到u所有的邻接点v的最短距离,那么当前可以更新的是起点到v的最短距离d[v]。直到s中包括所有点,算法结束,最后d数组就是起点到其他所有点的最短距离。
堆优化的话,就避免很多重复边的判断。
void Dijkstra(int st, int ed) {
memset(d, INF, sizeof(d));
memset(vis, false, sizeof(vis));
d[st] = 0;
for (int i = 0; i < n; i++) {
int u = -1, MIN = INF;
for (int j = 0; j < n; j++) {
if (vis[j] == false && d[j] < MIN) {
MIN = d[j];
u = j;
}
}
if (u == -1) return;
vis[u] = true;
for (int v = 0; v < n; v++) {
if (vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]) {
d[v] = d[u] + G[u][v];
}
}
}
}
堆优化。
struct edge {
int v;
int d;//距离
edge(){}
edge(int _v, int _d) {
v = _v;
d = _d;
}
};
vector<edge> E[maxn];
void Clear() {
for (int i = 0; i < maxn; i++) {
E[i].clear();
}
memset(pre, 0, sizeof(pre));
}
struct node {
int v;
int d;
bool operator<(const node &a)const{
return d > a.d;
}
};
void Dijkstra(int st, int ed) {
memset(d, INF, sizeof(d));
memset(minCost, INF, sizeof(minCost));
memset(vis, false, sizeof(vis));
d[st] = 0;
minCost[st] = 0;
priority_queue<node> q;
q.push(node{st, 0});
while (!q.empty()) {
node f = q.top(); q.pop();
int u = f.v;
if (vis[u] == true) continue;
vis[u] = true;
for (int i = 0; i < E[u].size(); i++) {
int v = E[u][i].v;
if (vis[v] == true) continue;
if (d[v] > d[u] + E[u][i].d) {
d[v] = d[u] + E[u][i].d;
pre[v] = u;
q.push(node{v, d[v]});
}
}
}
}
Bellman-Ford,复杂度O(n*E),顶点数n,边数E
void bellman-ford() {
for (int i = 0; i < n - 1; i++) {//最多n-1次
for (int u = 0; u < n; u++) {
for (int j = 0; j < Adj[u].size(); j++) {
int v = Adj[u][j].v;
int dis = Adj[u][j].dis;
if (d[u] + dis < d[v]) {
d[v] = d[u] + dis;
}
}
}
}
}
SPFA,复杂度O(k*E),k平均值一般等于2
spfa算法就是对bellman-ford的一种队列优化,避免了很多无意义的判断和操作。
bool SPFA(int s) {
memset(inq, false, sizeof(inq));
memset(num, 0, sizeof(num));
memset(d, INF, sizeof(d));
prority_queue<int> q;
q.push(s);
inq[s] = true;
num[s]++;
d[s] = 0;
while (!q.empty()) {
int u = q.top(); q.pop();
inq[u] = false;
//
for (int j = 0; j < Adj[u].size(); j++) {
int v = Adj[u][j].v;
int dis = Adj[u][j].dis;
if (d[u] + dis < d[v]) {
d[v] = d[u] + dis;
if (!inq[v]) {
inq[v] = true;
q.push(v);
num[v]++;
if (num[v] > n-1) return false;
}
}
}
}
return true;
}