第三章图论(三)

单源最短路的扩展应用

例题:选择最佳路线(HDOJ2680)
原题链接
问题描述
有一天,琪琪想拜访她的一位朋友。 由于她容易晕车,她想尽快到达朋友家。 现在给您一张城市交通路线图,以及琪琪家附近的车站,以便她乘坐。 Kiki可以在任何车站换公共汽车。 请找出琪琪需要花费的最少时间。 为方便起见,如果城市有n个公交车站,则车站将被表示为整数1,2,3…n。
输入
有多组测试用例。
每组样例均以三个整数n,m和s开头,(n <1000,m <20000,1 = 随后 m行,每行包含三个整数p,q,t(0 接下来一行是一个整数 w(0 接下来一行是w个整数,代表这些站的编号。
输出
每个样例一行输出:Kiki需要花费的最少时间,如果找不到这样的路线,只需输出“ -1”即可。
样例输入:
5 8 5
1 2 2
1 5 3
1 3 4
2 4 7
2 5 6
2 3 5
3 5 1
4 5 1
2
2 3
4 3 4
1 2 3
1 3 4
2 3 2
1
1
样例输出
1
-1
——————————————————————————————————————————————————
Scanner 和 BufferedReader 的多组测试样例如何读入的问题

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
    static int INF = Integer.MAX_VALUE >> 1;
    static int N = 1010;
    static int M = 21010;
    static int n;
    static int m;
    static int T;
    static int[] h = new int[N];
    static int[] w = new int[M];
    static int[] e = new int[M];
    static int[] ne = new int[M];
    static int idx = 0;
    static boolean[] st = new boolean[N];
    static int[] dist = new int[N];
    static int[] q = new int[N];

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while (true) {//不知道如何读入多组...
            String[] s1 = br.readLine().split(" ");
            n = Integer.parseInt(s1[0]);
            m = Integer.parseInt(s1[1]);
            T = Integer.parseInt(s1[2]);
            Arrays.fill(h, -1);
            idx = 0;
            while (m-- > 0) {
                String[] s2 = br.readLine().split(" ");
                int a = Integer.parseInt(s2[0]);
                int b = Integer.parseInt(s2[1]);
                int c = Integer.parseInt(s2[2]);
                add(a, b, c);
            }
            int s = Integer.parseInt(br.readLine());
            String[] s3 = br.readLine().split(" ");
            for (int i = 0; i < s; i++) {
                int ver = Integer.parseInt(s3[i]);
                add(0, ver, 0);
            }
            System.out.println(spfa());
        }
    }

    private static void add(int a, int b, int c) {
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx++;
    }

    private static int spfa() {
        Arrays.fill(dist, INF);
        dist[0] = 0;
        int hh = 0, tt = 1;
        q[0] = 0;
        while (hh != tt) {
            int t = q[hh++];
            if (hh == N) hh = 0;
            st[t] = false;
            for (int i = h[t]; i != -1; i = ne[i]) {
                int j = e[i];
                if (dist[j] > dist[t] + w[i]) {
                    dist[j] = dist[t] + w[i];
                    if (!st[j]) {
                        q[tt++] = j;
                        if (tt == N) tt = 0;
                        st[j] = true;
                    }
                }
            }
        }
        if (dist[T] == INF) return -1;
        return dist[T];
    }
}

例题:拯救大兵瑞恩



输入样例:
4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1
输出样例:
14
第三章图论(三)_第1张图片
————————————————————————————————————————————————————
【CE】了

import java.util.*;

public class Main {
    static int INF = Integer.MAX_VALUE >> 1;
    static int N = 11;
    static int M = N * N;
    static int E = 400;
    static int P = 1 << 10;
    static int n;
    static int m;
    static int p;
    static int k;
    static int[] h = new int[M];
    static int[] e = new int[E];
    static int[] w = new int[E];
    static int[] ne = new int[E];
    static int idx = 0;
    static int[][] g = new int[N][N];
    static int[] key = new int[M];
    static boolean[][] st = new boolean[M][P];
    static int[][] dist = new int[M][P];
    static Set<Pair> edges = new HashSet<>();
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        p = sc.nextInt();
        k = sc.nextInt();
        for (int i = 1, t = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                g[i][j] = t++;
            }
        }
        Arrays.fill(h, -1);
        while (k-- > 0) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();
            int c = sc.nextInt();
            int a = g[x1][y1];
            int b = g[x2][y2];
            edges.add(new Pair(a, b));
            edges.add(new Pair(b, a));//这两条边用过了
            if (c != 0) {
                add(a, b, c);
                add(b, a, c);
            }
        }
        build();
        int s = sc.nextInt();
        while (s-- > 0) {
            int x = sc.nextInt();
            int y = sc.nextInt();
            int id = sc.nextInt();
            key[g[x][y]] |= 1 << id - 1;
        }
        System.out.println(bfs());
    }

    private static int bfs() {
        LinkedList<Pair> q = new LinkedList<>();//双端队列
        Arrays.fill(dist, INF);
        dist[1][0] = 0;
        q.add(new Pair(1, 0));
        while (!q.isEmpty()) {
            Pair t = q.poll();
            if (st[t.x][t.y]) continue;
            st[t.x][t.y] = true;
            if (t.x == n * m) return dist[t.x][t.y];
            if (key[t.x] != 0) {
                int state = t.y | key[t.x];
                if (dist[t.x][state] > dist[t.x][t.y]) {
                    dist[t.x][state] = dist[t.x][t.y];
                    q.addFirst(new Pair(t.x, state));
                }
            }
            for (int i = h[t.x]; i != -1; i = ne[i]) {
                int j = e[i];
                if (w[i] != 0 && (t.y >> w[i] - 1 & 1) == 0) continue;
                if (dist[j][t.y] > dist[t.x][t.y] + 1) {
                    dist[j][t.y] = dist[t.x][t.y] + 1;
                    q.add(new Pair(j, t.y));
                }
            }
        }
        return -1;
    }

    private static void build() {
        int[] dx = {-1, 0, 1, 0};
        int[] dy = {0, 1, 0, -1};
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                for (int u = 0; u < 4; u++) {
                    int x = i + dx[u];
                    int y = j + dy[u];
                    if (x == 0 || x > n || y == 0 || y > m) continue;
                    int a = g[i][j];
                    int b = g[x][y];
                    Pair p = new Pair(a, b);
                    //感觉用这个contains有问题
                    if (!edges.contains(p)) add(a, b, 0);
                }
            }
        }
    }

    private static void add(int a, int b, int c) {
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx++;
    }
}
class Pair{
    int x;
    int y;

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

例题:最短路计数
【题目描述】
给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1∼N。问从顶点 1 开始,到其他每个点的最短路有几条。
【输入】
给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1∼N。问从顶点 1 开始,到其他每个点的最短路有几条。
【输出】
输出 N 行,每行一个非负整数,第 i 行输出从顶点 1 到顶点 i 有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点 i 则输出 0。
【输入样例】
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
【输出样例】
1
1
1
2
4
【提示】
样例解释
1 到 5 的最短路有 4 条,分别为 2 条 1→2→4→5 和 2 条 1→3→4→5(由于 4→5 的边有 2 条)。
数据范围:
对于 20% 的数据,N≤100;
对于 60% 的数据,N≤1000;
对于 100% 的数据,1≤N≤100000,0≤M≤200000。
————————————————————————————————————————————————————

import java.util.*;

public class Main {
    static int INF = Integer.MAX_VALUE >> 1;
    static int N = 100010;
    static int M = 400010;
    static int mod = 100003;
    static int n;
    static int m;
    static int[] h = new int[N];
    static int[] e = new int[M];
    static int[] ne = new int[M];
    static int idx = 0;
    static int[] dist = new int[N];
    static int[] cnt = new int[N];
    static int[] q = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        Arrays.fill(h, -1);
        while (m-- > 0) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            add(a, b);
            add(b, a);
        }
        bfs();
        for (int i = 1; i <= n; i++) {
            System.out.println(cnt[i]);
        }
    }

    private static void bfs() {
        Arrays.fill(dist, INF);
        dist[1] = 0;
        cnt[1] = 1;
        int hh = 0, tt = 0;
        q[0] = 1;
        while (hh <= tt) {
            int t = q[hh++];
            for (int i = h[t]; i != -1; i = ne[i]) {
                int j = e[i];
                if (dist[j] > dist[t] + 1) {
                    dist[j] = dist[t] + 1;
                    cnt[j] = cnt[t];
                    q[++tt] = j;
                }else if (dist[j] == dist[t] + 1) {
                    cnt[j] = (cnt[j] + cnt[t]) % mod;
                }
            }
        }
    }

    private static void add(int a, int b) {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }
}

例题:383. 观光
第三章图论(三)_第2张图片

import java.util.*;

public class Main {
    static int INF = Integer.MAX_VALUE >> 1;
    static int N = 1010;
    static int M = 10010;
    static int n;
    static int m;
    static int S;
    static int T;
    static int[] h = new int[N];
    static int[] w = new int[M];
    static int[] e = new int[M];
    static int[] ne = new int[M];
    static int idx = 0;
    static int[][] dist = new int[N][2];
    static int[][] cnt = new int[N][2];
    static boolean[][] st = new boolean[N][2];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int cases = sc.nextInt();
        while (cases-- > 0) {
            n = sc.nextInt();
            m = sc.nextInt();
            Arrays.fill(h, -1);
            idx = 0;
            while (m-- > 0) {
                int a = sc.nextInt();
                int b = sc.nextInt();
                int c = sc.nextInt();
                add(a, b, c);
            }
            S = sc.nextInt();
            T = sc.nextInt();
            System.out.println(dijkstra());
        }
    }

    private static int dijkstra() {
        for (boolean[] x : st) Arrays.fill(x, false);
        for (int[] x : cnt) Arrays.fill(x, 0);
        for (int[] x : dist) Arrays.fill(x, INF);
        dist[S][0] = 0;
        cnt[S][0] = 1;
        Queue<Ver> heap = new PriorityQueue<>(new Comparator<Ver>() {
            @Override
            public int compare(Ver o1, Ver o2) {
                return o1.dist - o2.dist;
            }
        });
        heap.add(new Ver(S, 0, 0));
        while (!heap.isEmpty()) {
            Ver t = heap.poll();
            int ver = t.ver;
            int type = t.type;
            int distance = t.dist;
            int count = cnt[ver][type];
            if (st[ver][type]) continue;
            st[ver][type] = true;
            for (int i = h[ver]; i != -1; i = ne[i]) {
                int j = e[i];
                if (dist[j][0] > distance + w[i]) {
                    dist[j][1] = dist[j][0];
                    cnt[j][1] = cnt[j][0];
                    heap.add(new Ver(j, 1, dist[j][1]));
                    dist[j][0] = distance + w[i];
                    cnt[j][0] = count;
                    heap.add(new Ver(j, 0, dist[j][0]));
                }else if (dist[j][0] == distance + w[i]) {
                    cnt[j][0] += count;
                }else if (dist[j][1] > distance + w[i]) {
                    dist[j][1] = distance + w[i];
                    cnt[j][1] = count;
                    heap.add(new Ver(j, 1, dist[j][1]));
                }else if (dist[j][1] == distance + w[i]) {
                    cnt[j][1] += count;
                }
            }
        }
        int res = cnt[T][0];
        if (dist[T][0] + 1 == dist[T][1]) res += cnt[T][1];
        return res;
    }

    private static void add(int a, int b, int c) {
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx++;
    }
}
class Ver{
    int ver;
    int type;
    int dist;

    public Ver(int ver, int type, int dist) {
        this.ver = ver;
        this.type = type;
        this.dist = dist;
    }
}

你可能感兴趣的:(算法提高课)