[图论]最短路径

如果边权都是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 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值