2021-05-17

今天的这个题,前面一半没有绕湾子,直抒胸臆,求最短路径,没说的 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;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/awp0011/article/details/116947037