今天的这个题,前面一半没有绕湾子,直抒胸臆,求最短路径,没说的 dijkstra算法模板用上
后半部分是求最短路径的“成本和”,需要考虑的是如果有“多条最短路径”,需要将所有最短路径权值 累加到一起,但是相同的边不能重复相加
怎么办呢?
其实也不复杂,在求解最短路径的过程中记录一下:到每个节点的最短路径是由哪一个 父节点 来的即可
也就是
if (dist[nx] > dist[cur] + len) {
dist[nx] = dist[cur] + len;
from.get(nx).clear();
from.get(nx).add(next);
pq.add(new KV(nx, dist[nx]));//最短路径是由哪一个 父节点,最好是记录“边的数据”
} else if (dist[nx] == dist[cur.node] + len) {
from.get(nx).add(next);// 如果有多个相等父节点 就都记下来
}
然后中N向1再做1次bfs遍历,将用到边成本 累加起来
注意,线权值与k的乘积在相加中 会不会超过int
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.*;
public class Solution {
static final long INF = Long.MAX_VALUE >> 1;
static final int MaxN = 20000;
static final long[] dist = new long[MaxN + 3];
static final boolean[] vis = new boolean[MaxN + 3];
static final long[] kVal = new long[20];
static final ArrayList<ArrayList<int[]>> to = new ArrayList<>();
static final ArrayList<ArrayList<int[]>> from = new ArrayList<>();
static final PriorityQueue<KV> pq = new PriorityQueue<>(Comparator.comparingLong(o -> o.dist));
static final Queue<Integer> que = new LinkedList<>();
static int N, M, K;
static long ans;
static StreamTokenizer in;
public static void main(String[] args) throws IOException {
in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int T = nextInt();
init();
for (int tc = 1; tc <= T; tc++) {
readCase();
ans = 0;
work();
System.out.println("#" + tc + " " + ans);
}
}
static void work() {
dist[1] = 0;
pq.add(new KV(1, 0));
while (!pq.isEmpty()) {
KV cur = pq.poll();
for (int[] next : to.get(cur.node)) {
int nx = next[1];
int len = next[2];
if (dist[nx] > dist[cur.node] + len) {
dist[nx] = dist[cur.node] + len;
from.get(nx).clear();
from.get(nx).add(next);
pq.add(new KV(nx, dist[nx]));
} else if (dist[nx] == dist[cur.node] + len) {
from.get(nx).add(next);
}
}
}
vis[N] = true;
que.add(N);
while (!que.isEmpty()) {
int cur = que.poll();
for (int[] next : from.get(cur)) {
ans += next[2] * kVal[next[3]];
if (!vis[next[0]]) que.add(next[0]);
vis[next[0]] = true;
}
}
for (int i = 1; i <= N; i++) {
to.get(i).clear();
from.get(i).clear();
}
}
private static int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
static void readCase() throws IOException {
N = nextInt();
M = nextInt();
K = nextInt();
for (int i = 0; i < M; i++) {
int[] edge = new int[4];
edge[0] = nextInt();
edge[1] = nextInt();
edge[2] = nextInt();
edge[3] = nextInt();
to.get(edge[0]).add(edge);
}
for (int i = 1; i <= K; i++) {
kVal[i] = nextInt();
}
Arrays.fill(dist, INF);
Arrays.fill(vis, false);
}
static void init() {
for (int i = 0; i <= MaxN; i++) {
to.add(new ArrayList<>());
from.add(new ArrayList<>());
}
}
static class KV {
final int node;
final long dist;
KV(int n, long d) {
node = n;
dist = d;
}
}
}