🤠 原题地址
🤠 超级源点,到所有上商店的距离为 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++;
}
}