[java]最短路

图论

最短路径

例题:
743. 网络延迟时间
在这里插入图片描述

朴素Dijkstra

算法:

st:当前已确定最短距离的点的集合
dist[1] = 0, dist[i] = INF
for i  1 ~ n:
	t : 不在st中,距离最近的点
	将t加入st
	用t更新其他点的距离
class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        List<int[]>[] g = new List[n + 1];
        Arrays.setAll(g, (a) -> new ArrayList<>());
        for(int[] t : times){
            int a = t[0], b = t[1], c = t[2];
            g[a].add(new int[]{b, c});
        }
        int[] dist = new int[n + 1];
        boolean[] st = new boolean[n + 1];
        Arrays.fill(dist, 0x3f3f3f);
        dist[k] = 0;
        for(int i = 0; i < n; i++){
            int t = -1;
            for(int j = 1; j <= n; j++){
                if(!st[j] && (t == -1 || dist[t] > dist[j])){
                    t = j;
                }
            }
            st[t] = true;
            for(int[] nei : g[t]){
                int a = nei[0], b = nei[1];
                dist[a] = Math.min(dist[a], dist[t] + b);
            }
        }
        int res = 0;
        for(int i = 1; i <= n; i++){
            if(dist[i] == 0x3f3f3f) return -1;
            res = Math.max(res, dist[i]);
        }
        return res;
    }
}

Bellman-ford

算法:

for n次
	for  所有边 a , b, w
		dist[b] = Math.min(dist[b], dist[a] + w)
class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        int[] dist = new int[n + 1], backup = new int[n + 1];
        Arrays.fill(dist, 0x3f3f3f);
        dist[k] = 0;
        for(int i = 0; i < n; i++){
            backup = dist.clone();
            for(int[] t : times){
                int a = t[0], b = t[1], c = t[2];
                dist[b] = Math.min(dist[b], backup[a] + c);
            }
        }
        int ans = 0;
        for(int i = 1; i <= n; i++){
            if(dist[i] == 0x3f3f3f) return -1;
            ans = Math.max(ans, dist[i]);
        }
        return ans;
    }
}

SPFA

算法:

queue  <---  1
while queue不空
	 t  <---  queue.poll();
	 更新t的所有出边  t---w---b
	 	queue <--- b
class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        List<int[]>[] g = new List[n + 1];
        Arrays.setAll(g, (a) -> new ArrayList<>());
        for(int[] t : times){
            int a = t[0], b = t[1], c = t[2];
            g[a].add(new int[]{b, c});
        }
        int[] dist = new int[n + 1];
        boolean[] st = new boolean[n + 1];//st[i] : i是否在队列中
        Arrays.fill(dist, 0x3f3f3f);
        dist[k] = 0;
        st[k] = true;
        Deque<Integer> q = new ArrayDeque<>();
        q.offer(k);
        while(!q.isEmpty()){
            int cur = q.poll();
            st[cur] = false;
            for(int[] nei : g[cur]){
                int a = nei[0], b = nei[1];
                if(dist[a] > dist[cur] + b){
                    dist[a] = dist[cur] + b;
                    if(!st[a]) {
                        q.offer(a);
                        st[a] = true;
                    }
                }
            }
        }
        int res = 0;
        for(int i = 1; i <= n; i++){
            if(dist[i] == 0x3f3f3f) return -1;
            res = Math.max(res, dist[i]);
        }
        return res;
    }
}

spfa判断负环

拉近距离

题目背景

我是源点,你是终点。我们之间有负权环。 ——小明

题目描述

在小明和小红的生活中,有 N N N 个关键的节点。有 M M M 个事件,记为一个三元组 ( S i , T i , W i ) (S_i,T_i,W_i) (Si,Ti,Wi),表示从节点 S i S_i Si 有一个事件可以转移到 T i T_i Ti,事件的效果就是使他们之间的距离减少 W i W_i Wi

这些节点构成了一个网络,其中节点 1 1 1 N N N 是特殊的,节点 1 1 1 代表小明,节点 N N N 代表小红,其他代表进展的阶段。所有事件可以自由选择是否进行,但每次只能进行当前节点邻接的。请你帮他们写一个程序,计算出他们之间可能的最短距离。

输入格式

第一行,两个正整数 N , M N,M N,M

之后 M M M 行,每行 3 3 3 个空格隔开的整数 S i , T i , W i S_i,T_i,W_i Si,Ti,Wi

输出格式

一行,一个整数表示他们之间可能的最短距离。如果这个距离可以无限缩小,输出Forever love

样例 #1
样例输入 #1
3 3
1 2 3
2 3 -1
3 1 -10
样例输出 #1
-2
提示

对于 20 % 20\% 20% 数据, N ≤ 10 N \le 10 N10 M ≤ 50 M \le 50 M50

对于 50 % 50\% 50% 数据, N ≤ 300 N \le 300 N300 M ≤ 5000 M \le 5000 M5000

对于 100 % 100\% 100% 数据, 1 ≤ N ≤ 1 0 3 1\le N \le 10^3 1N103 1 ≤ M ≤ 1 0 4 1\le M \le 10^4 1M104 ∣ W i ∣ ≤ 100 |W_i|\le 100 Wi100,保证从节点 1 1 1 2 … N 2 \dots N 2N 有路径,从节点 N N N 1 … N − 1 1 \dots N - 1 1N1 有路径。

import java.util.*;

public class P2136 {
    static final int N = 1010, M = 10010, INF = 0x3f3f3f;
    static int n, m;
    static int[] dist = new int[N], cnt = new int[N];
    static boolean[] st = new boolean[N];
    static List<int[]>[] g = new List[N];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        Arrays.setAll(g, (a) -> new ArrayList<>());
        int s, t, w;
        for(int i = 0; i < m; i++){
            s = sc.nextInt();
            t = sc.nextInt();
            w = sc.nextInt();
            g[s].add(new int[]{t, -w});
        }

        boolean f1 = spfa(1);
        int ans1 = dist[n];
        boolean f2 = spfa(n);
        int ans2 = dist[1];
        if(f1 || f2){
            System.out.println("Forever love");
        }else{
            System.out.println(Math.min(ans1, ans2));
        }

    }

    private static boolean spfa(int x) {
        Arrays.fill(dist, INF);
        Arrays.fill(cnt, 0);
        dist[x] = 0;
        Deque<Integer> q = new ArrayDeque<>();
        q.offer(x);
        st[x] = true;
        while(!q.isEmpty()){
            int cur = q.poll();
            st[cur] = false;
            for(int[] nei : g[cur]){
                int t = nei[0], w = nei[1];
                if(dist[t] > dist[cur] + w){
                    dist[t] = dist[cur] + w;
                    cnt[t] = cnt[cur] + 1;
                    if(cnt[t] >= n) {
                        return true;
                    }
                    if(!st[t]){
                        q.offer(t);
                        st[t] = true;
                    }
                }
            }
        }
        return false;
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值