如果边权都是1直接bfs求最短路即可。如果边权是1/0,那么就把0在队头插入即可,相当于跳过了这条边,时间复杂度O(m)。
SPFA:就是把优先队列改成队列,然后while改成下面的就可以了,松弛操作和dijkstra一样,就是多了个used数组,SPFA可以处理有负权边的最短路。
while(!qi.empty()){
int u = qi.front(); qi.pop();
used[u] = false;
for (int i = 0; i < g[u].size(); ++i){
int v = g[u][i].v;
if (d[v] > d[u] + g[u][i].c){
d[v] = d[u] + g[u][i].c;
if (!used[v]){
used[v] = true;
qi.push(v);
}
}
}
}
dijkstra算法
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int maxn = 2e5 + 5;
struct edge{
int v, c;
};
vector<edge> g[maxn];
int d[maxn];
int main()
{
int n, m, q, u, v, c;
scanf("%d %d %d", &n, &m, &q);
for (int i = 1; i <= m; ++i){
scanf("%d %d %d", &u, &v, &c);
g[u].push_back(edge{v, c});
//下面这条是无向图
//g[v].push_back(edge{u, c});
}
memset(d, 0x3f, sizeof(d));
d[q] = 0;
priority_queue<pii, vector<pii>, greater<pii> > pqi;
pqi.push(pii(0, q));
while(!pqi.empty()){
pii e = pqi.top(); pqi.pop();
if (d[e.second] < e.first) continue;
int u = e.second, c = e.first;
for (int i = 0; i < g[u].size(); ++i){
if (d[g[u][i].v] > c + g[u][i].c){
d[g[u][i].v] = c + g[u][i].c;
pqi.push(pii(d[g[u][i].v], g[u][i].v));
}
}
}
for (int i = 1; i <= n; ++i) printf("%d ", d[i]);
return 0;
}
再来个Java版的
import java.io.*;
import java.util.*;
public class Main {
static class Edge implements Comparable<Edge> {
int v, c;
public Edge(int v, int c) {
this.v = v;
this.c = c;
}
@Override
public int compareTo(Edge e) {
return this.c - e.c;
}
}
static int d[];
static ArrayList<Edge>[] g;
public static void main(String[] args) {
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
InputReader input = new InputReader(inputStream);
PrintWriter out = new PrintWriter(outputStream);
int n, m, q;
n = input.nextInt(); m = input.nextInt(); q = input.nextInt();
g = new ArrayList[n + 1];
for (int i = 1; i <= n; i++) {
g[i] = new ArrayList<>();
}
for (int i = 1; i <= m; ++i){
int u, v, c;
u = input.nextInt(); v = input.nextInt(); c = input.nextInt();
g[u].add(new Edge(v, c));
//下面这条是无向图
//g[v].push_back(edge{u, c});
}
d = new int[n + 1];
Arrays.fill(d, Integer.MAX_VALUE);
d[q] = 0;
PriorityQueue<Edge> queue = new PriorityQueue<>();
queue.add(new Edge(0, q));
while(!queue.isEmpty()){
Edge cur = queue.poll();
if (d[cur.c] < cur.v) continue;
int u = cur.c, c = cur.v;
for (Edge e : g[u]){
if (d[e.v] > c + e.c){
d[e.v] = c + e.c;
queue.add(new Edge(d[e.v], e.v));
}
}
}
for (int i = 1; i <= n; ++i)
out.print(d[i] + " ");
out.close();
}
static class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
}
}
floyd算法(多源最短路径)
for (int k = 1; k <= n; ++k){
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= n; ++j){
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
}
}
bellman-ford判负环
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<utility>
#include<vector>
#include<queue>
#define maxn 5505
#define inf 0x3f3f3f3f
using namespace std;
struct edge{
edge() : u(0), v(0), c(0) {}
edge(int a, int b, int c) : u(a), v(b), c(c) {}
int u, v, c;
}e[maxn];
int d[maxn], n, m;
bool f()
{
memset(d, 0, sizeof(d));
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
edge t = e[j];
if (d[t.v] > d[t.u] + t.c){
d[t.v] = d[t.u] + t.c;
if (i == n) return true;
}
}
}
return false;
}
拓扑排序
vector<int> topoarr;
void topo()
{
stack<int> si;
for (int i = 1; i <= n; ++i) if (in[i] == 0) si.push(i);
while (!si.empty()){
int u = si.top(); si.pop();
topoarr.push_back(u);
for (int v = 0; v < g[u].size(); ++v){
if (--in[g[u][v]] == 0) si.push(g[u][v]);
}
}
return ;
}