Submission #3609392


Source Code Expand

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

public class Main {

    static int N, M, S, T;
    static Edge[] E;

    public static void main(String[] args) throws IOException {
        FastScanner sc = new FastScanner(System.in);
        N = sc.nextInt();
        M = sc.nextInt();
        S = sc.nextInt()-1;
        T = sc.nextInt()-1;
        E = new Edge[M];
        for (int i = 0; i < M; i++) {
            E[i] = new Edge(sc.nextInt()-1, sc.nextInt()-1, sc.nextInt());
        }

        System.out.println(solve());
    }

    static class Edge {
        final int a, b, d;

        public Edge(int a, int b, int d) {
            this.a = a;
            this.b = b;
            this.d = d;
        }

        int opposite(int x) {
            return a == x ? b : a;
        }
    }

    static class State implements Comparable<State> {
        int a;
        long d;

        public State(int a, long d) {
            this.a = a;
            this.d = d;
        }

        @Override
        public int compareTo(State o) {
            return Long.compare(d, o.d);
        }
    }

    static int MOD = 1_000_000_007;
    static long INF = Long.MAX_VALUE / 2;

    static long solve() throws IOException {
        Edge[][] G = adjB(N, E);

        Result rs = calc(G, S);
        Result rt = calc(G, T);
        long dist = rs.dist[T];

        long collision = 0;
        int vcnt = 0;
        for (int i = 0; i < N; i++) {
            if( rs.dist[i] == dist / 2 && rt.dist[i] == dist / 2 ) {
                long ab = (long)rs.time[i] * rt.time[i] % MOD;
                collision += ab * ab;
                collision %= MOD;
                vcnt++;
            }
        }

        int ecnt = 0;
        for (Edge e : E) {
            int a = rs.dist[e.a] < rs.dist[e.b] ? e.a : e.b;
            int b = e.opposite(a);
            int d = e.d;
            if( rs.dist[a] + d == rs.dist[b]
                    && rs.dist[b] + rt.dist[b] == dist
                    // && rs.dist[a] + rt.dist[a] == dist 必要ないっぽい
                    && rs.dist[a] < rt.dist[a]
                    && rs.dist[b] > rt.dist[b] )
            {
                long ab = (long)rs.time[a] * rt.time[b] % MOD;
                collision += ab * ab;
                collision %= MOD;
                ecnt ++;
            }
        }

        int time = rs.time[T];
        return ((long)time * time - collision + MOD) % MOD;
    }

    static class Key {
        int a, b;

        public Key(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Key key = (Key) o;
            return a == key.a &&
                    b == key.b;
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b);
        }
    }

    // (v, w) intersect (x, y)
    static boolean isCross(long v, long w, long x, long y) {
        if( v <= x ) {
            return x < w;
        } else {
            return v < y;
        }
    }

    static class Result {
        long[] dist;
        int[] time;

        public Result(long[] dist, int[] time) {
            this.dist = dist;
            this.time = time;
        }
    }

    static Result calc(Edge[][] G, int from) {
        long[] dist = new long[N];
        int[] time = new int[N];
        Arrays.fill(dist, INF);
        Arrays.fill(time, -1);

        PriorityQueue<State> q = new PriorityQueue<>();
        q.add(new State(from, 0));
        dist[from] = 0;
        time[from] = 1;

        while( !q.isEmpty() ) {
            State s = q.poll();
            if( dist[s.a] != s.d ) continue;

            for (Edge e : G[s.a]) {
                int next = e.opposite(s.a);
                long nd = s.d + e.d;
                if( dist[next] > nd ) {
                    dist[next] = nd;
                    time[next] = time[s.a];
                    q.add( new State(next, nd) );

                } else if( dist[next] == nd ) {
                    time[next] += time[s.a];
                    time[next] %= MOD;
                }
            }
        }
        return new Result(dist, time);
    }

    static Edge[][] adjB(int n, Edge[] E) {
        Edge[][] adj = new Edge[n][];
        int[] cnt = new int[n];
        for (Edge e : E) {
            cnt[e.a]++;
            cnt[e.b]++;
        }
        for (int i = 0; i < n; i++) {
            adj[i] = new Edge[cnt[i]];
        }
        for (Edge e : E) {
            adj[e.a][--cnt[e.a]] = e;
            adj[e.b][--cnt[e.b]] = e;
        }
        return adj;
    }

    @SuppressWarnings("unused")
    static class FastScanner {
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        FastScanner(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
            tokenizer = null;
        }

        String next() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        String nextLine() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    return reader.readLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken("\n");
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }
    }
}

Submission Info

Submission Time
Task E - Avoiding Collision
User kusomushi
Language Java8 (OpenJDK 1.8.0)
Score 700
Code Size 6471 Byte
Status AC
Exec Time 556 ms
Memory 68120 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 700 / 700
Status
AC × 4
AC × 22
Set Name Test Cases
Sample sample01.txt, sample02.txt, sample03.txt, sample04.txt
All 01.txt, 02.txt, 03.txt, 04.txt, 05.txt, 06.txt, 07.txt, 08.txt, 09.txt, 10.txt, 11.txt, 12.txt, 13.txt, 14.txt, 15.txt, 16.txt, 17.txt, 18.txt, sample01.txt, sample02.txt, sample03.txt, sample04.txt
Case Name Status Exec Time Memory
01.txt AC 488 ms 65512 KB
02.txt AC 520 ms 64852 KB
03.txt AC 523 ms 68120 KB
04.txt AC 461 ms 63688 KB
05.txt AC 550 ms 64508 KB
06.txt AC 438 ms 56912 KB
07.txt AC 556 ms 64080 KB
08.txt AC 332 ms 46256 KB
09.txt AC 478 ms 61664 KB
10.txt AC 470 ms 63736 KB
11.txt AC 496 ms 62124 KB
12.txt AC 502 ms 63740 KB
13.txt AC 551 ms 61960 KB
14.txt AC 453 ms 63760 KB
15.txt AC 529 ms 65036 KB
16.txt AC 495 ms 64368 KB
17.txt AC 476 ms 65752 KB
18.txt AC 493 ms 64488 KB
sample01.txt AC 70 ms 19540 KB
sample02.txt AC 70 ms 19664 KB
sample03.txt AC 72 ms 20820 KB
sample04.txt AC 71 ms 19668 KB