Floyd
纯暴力,三个 for
循环
复杂度: (O(V^3))
for(int k = 1;k <= n;k++){
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
if(dis[i][k] + dis[k][j] < dis[i][j]){
//...
}
}
}
}
Bellman-Ford
用边去进行松弛操作,可以判环
复杂度: (O(VE))
#include<bits/stdc++.h>
using namespace std;
const int maxm = 2e5 + 10;
const int maxn = 1e5 + 10;
struct E {
int from, to, w;
}Edges[maxm];
int dis[maxn];
int n, m, s;
bool bellman_ford(int s) {
for (int i = 1; i < n; i++) {//松弛n-1次
for (int j = 0; j < m; j++) {
int f = Edges[j].from, t = Edges[j].to, w = Edges[j].w;
if (dis[t] > dis[f] + w) {
dis[t] = dis[f] + w;
}
}
}
for (int j = 0; j < m; j++) {
int f = Edges[j].from, t = Edges[j].to, w = Edges[j].w;
if (dis[t] > dis[f] + w) {
return false;//负环
}
}
return true;
}
int main() {
scanf("%d %d %d", &n, &m, &s);
memset(dis, 0x3f, sizeof dis);
dis[s] = 0;//注意dis的初始化
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &Edges[i].from, &Edges[i].to, &Edges[i].w);
if (Edges[i].from == s) {
dis[Edges[i].to] = Edges[i].w;//初始化
}
}
bellman_ford(s);
for (int i = 1; i <= n; i++) {
printf("%d%s", dis[i], i == n ? "
" : " ");
//printf("%d%c",dis[i],"
"[i==n]);
}
}
Dijkstra
复杂度 : (O(VlogV+E))
struct Node {
long long d;
int u;
bool operator < (const Node& rhs)const {
//rhs,right-hand-side
return d > rhs.d;
}
};
void dijkstra(int s) {
priority_queue<Node>Q;
for (int i = 1;i <= n;i++) {
d[i] = INF;
}
d[s] = 0;
memset(vis, 0, sizeof(vis));
Q.push(Node{ 0,s });
while (!Q.empty()) {
Node x = Q.top();Q.pop();
int u = x.u;
if (vis[u]) {
continue;
}
vis[u] = 1;
for (int i = 0;i < G[u].size();i++) {
Edge e = edges[G[u][i]];
if (d[e.to] > d[u] + e.dist) {
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
Q.push(Node{ d[e.to],e.to });
}
}
}
}
SPFA
(O(kE)) ,(k) 为每个节点入队次数
最坏 (O(EV))
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
struct Edge {
int to, w, next;
}E[maxn];
int head[maxn], tot;
void AddEdge(int from, int to, int w) {
E[tot] = Edge{ to,w,head[from] };
head[from] = tot++;
}
int n, m, s;
const int inf = 0x3f3f3f3f;// inf > (1e9)
int dis[maxn], vis[maxn];
void spfa() {
queue<int> q;
memset(dis, 0x3f, sizeof(int) * (n + 10));
memset(vis, 0, sizeof(int) * (n + 10));
q.push(s); dis[s] = 0; vis[s] = 1; //第一个顶点入队,进行标记
while (!q.empty()) {
int u = q.front();
q.pop(); vis[u] = 0;
for (int i = head[u]; ~i; i = E[i].next) {
int v = E[i].to;
if (dis[v] > dis[u] + E[i].w) {
dis[v] = dis[u] + E[i].w;
if (vis[v] == 0) {
//此处判环
//if(++cnt[v] >= n) 有负环
vis[v] = 1;
q.push(v);
}
}
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &s);
memset(head, 0xff, sizeof(int) * (n + 10));
tot = 0;
for (int i = 0; i < m; i++) {
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
AddEdge(a, b, w);
}
spfa();
for (int i = 1; i <= n; i++) {
printf("%d%c", dis[i] == 0x3f3f3f3f ? (1 << 31) - 1 : dis[i], "
"[i == n]);
}
}