AcWing 1488. 最短距离 java (单源最短路)

在这里插入图片描述

🤠 原题地址
🤠 超级源点,到所有上商店的距离为 0,而且是有向的,0 -> 商店,某个村庄到商店的距离转为 超级源点 到 商店再 某个村庄的最近距离
🤠 堆(PriorityQueue),找当前已知最短距离的节点的下一个最近的节点时间复杂度 O( logm)

import java.io.*;
import java.util.*;


public class Main
{
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
	static int N = 300010;// 无向边=有向边*2= 200000; 再加上超级源点的边()

	// 邻接表存图
	static int[] h = new int[N];
	static int[] e = new int[N];
	static int[] ne = new int[N];
	static boolean[] st = new boolean[N];
	static int[] w = new int[N];
	static int[] dist = new int[N];// 距离数组
	static int idx, n, m;

	public static void main(String[] args) throws IOException
	{
		String[] split = in.readLine().split(" ");
		n = Integer.parseInt(split[0]);
		m = Integer.parseInt(split[1]);
		Arrays.fill(h, -1);
		for (int i = 0; i < m; i++)
		{
			String[] split2 = in.readLine().split(" ");
			int a = Integer.parseInt(split2[0]);
			int b = Integer.parseInt(split2[1]);
			int c = Integer.parseInt(split2[2]);

			add(a, b, c);
			add(b, a, c);
		}

//		输入商店,并记录超级源点
		int k = Integer.parseInt(in.readLine());
		while (k-- > 0)
		{
			int num = Integer.parseInt(in.readLine());
			add(0, num, 0);// 超级源点到商店的距离都为 0
		}
		dijkstra();

		int q = Integer.parseInt(in.readLine());
		while (q-- > 0)
		{
			int x = Integer.parseInt(in.readLine());
			System.out.println(dist[x]);
		}

	}

	private static void dijkstra()
	{
		Arrays.fill(dist, 0x3f3f3f3f);
		dist[0] = 0;// 超级源点的下标为 0 ,从超级源点开始做单源最短路

//		传个比较器,按照距离升序排序
		PriorityQueue<Pair> heap = new PriorityQueue<>((o1, o2) -> o1.d - o2.d);

		heap.add(new Pair(0, 0));// 起点就是0, dist 的距离 是 0 -> 各商店 -> 各村的距离

		while (heap.size() != 0)
		{
			Pair t = heap.poll();// 小根堆,根是距离最小的点
			int x = t.x;
			int d = t.d;
			if (st[x])
				continue;

			st[x] = true;

//			用当前距离最小的点去更新其他节点
			for (int i = h[x]; i != -1; i = ne[i])
			{
				int j = e[i];
//				dist[j] 是目前 j 到源的距离 ; d 是 t 到 源 的距离 ,w[i] t到j 的距离
				if (dist[j] > d + w[i])
				{
					dist[j] = d + w[i];
					heap.add(new Pair(dist[j], j));
				}
			}
		}

	}

	static class Pair
	{
		int d;// 存到该点的距离
		int x;// 点

		public Pair(int d, int x)
		{
			super();
			this.d = d;
			this.x = x;
		}
	}

	/**
	 * a -> b
	 * 
	 * @param a 起点
	 * @param b 终点
	 * @param c 权重
	 */
	private static void add(int a, int b, int c)
	{
		e[idx] = b; 
		w[idx] = c;
		ne[idx] = h[a];
		h[a] = idx++;
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值