最短路径:
1,贝尔曼·富德-bellman·ford:单元最短路,暴力遍历每条边去更新答案。不能有负环
根据s已知的答案去更新e的答案:
s-v->e: ans[e] = min(ans[e], ans[s]+v)
复杂度O(nxm) n:节点数 m:边数
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct edge {
int s, e, v;
};
edge edg[200005];
int n, m, s, edg_cnt, ans[100005];
void add_edg(int a, int b, int c) {
edg[edg_cnt].s = a;
edg[edg_cnt].e = b;
edg[edg_cnt].v = c;
edg_cnt++;
}
int main() {
memset(ans, 0x3f, sizeof(ans));
scanf("%d%d%d", &n, &m, &s);
for (int i = 0; i < m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edg(a, b, c);
add_edg(b, a, c);
}
ans[s] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < edg_cnt; j++) {
ans[edg[j].e] = min(ans[edg[j].e], ans[edg[j].s] + edg[j].v);
}
}
for (int i = 1; i <= n; i++) {
if (ans[i] != 0x3f3f3f3f) printf("%d\n", ans[i]);
else printf("-1\n");
}
return 0;
}
优化:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct edge {
int s, e, v;
};
edge edg[200005];
int n, m, s, edg_cnt, ans[100005];
void add_edg(int a, int b, int c) {
edg[edg_cnt].s = a;
edg[edg_cnt].e = b;
edg[edg_cnt].v = c;
edg_cnt++;
}
int main() {
memset(ans, 0x3f, sizeof(ans));
scanf("%d%d%d", &n, &m, &s);
for (int i = 0; i < m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edg(a, b, c);
add_edg(b, a, c);
}
ans[s] = 0;
for (int i = 1; i <= n; i++) {
int flag = 0;
for (int j = 0; j < edg_cnt; j++) {
//ans[edg[j].e] = min(ans[edg[j].e], ans[edg[j].s] + edg[j].v);
if (ans[edg[j].e] > ans[edg[j].s] + edg[j].v) {
ans[edg[j].e] = ans[edg[j].s] + edg[j].v;
flag = 1;
}
}
if (flag == 0) break;
}
for (int i = 1; i <= n; i++) {
if (ans[i] != 0x3f3f3f3f) printf("%d\n", ans[i]);
else printf("-1\n");
}
return 0;
}
2,基于队列优化的贝尔曼·富德算法-bellman·ford(国内也叫spfa):
复杂度O(nxm) n:节点数 m:边数
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
struct edge {
int e, v, next;
};
edge edg[200005];
int n, m, s, edg_cnt, ans[100005], head[100005], mark[100005];
void add_edg(int a, int b, int c) {
edg[edg_cnt].e = b;
edg[edg_cnt].v = c;
edg[edg_cnt].next = head[a];
head[a] = edg_cnt++;
}
int main() {
memset(ans, 0x3f, sizeof(ans));
memset(head, -1, sizeof(head));
scanf("%d%d%d", &n, &m, &s);
for (int i = 0; i < m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edg(a, b, c);
add_edg(b, a, c);
}
ans[s] = 0;
queue<int> que;
que.push(s);
while (!que.empty()) {
int temp = que.front();
que.pop();
mark[temp] = 0;
for (int i = head[temp]; i != -1; i = edg[i].next) {
int e = edg[i].e, v = edg[i].v;
if (ans[e] > ans[temp] + v) {
ans[e] = ans[temp] + v;
if (mark[e] == 0) {
que.push(e);
mark[e] = 1;
}
}
}
}
for (int i = 1; i <= n; i++) {
if (ans[i] != 0x3f3f3f3f) printf("%d\n", ans[i]);
else printf("-1\n");
}
return 0;
}