Cod sursa(job #3296938)

Utilizator claudiu.belciugBelciug Claudiu claudiu.belciug Data 19 mai 2025 00:15:43
Problema Distante Scor 10
Compilator java Status done
Runda Arhiva de probleme Marime 6.25 kb
// SPDX-License-Identifier: BSD-3-Clause

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

public class Main {
    static class Task {
        public static final String INPUT_FILE = "distante.in";
        public static final String OUTPUT_FILE = "distante.out";

        static final long INF = Long.MAX_VALUE / 4; // o valoare mare (nu chiar MAX ca să evităm overflow)
        static int N, M, S;
        static int[] head, to, cost, nxt;
        static int edgeCnt;

        // Lista de răspunsuri pentru fiecare graf
        ArrayList<String> results = new ArrayList<>();

        public void solve() {
            readInput();
            writeOutput();
        }

        /* ============================ Citire ============================ */
        private void readInput() {
            try {
                Scanner sc = new Scanner(new BufferedReader(new FileReader(INPUT_FILE)));
                int T = sc.nextInt(); // numărul de grafuri

                for (int t = 0; t < T; t++) {
                    // 1. Citim numărul de noduri, muchii și sursa
                    N = sc.nextInt();
                    M = sc.nextInt();
                    S = sc.nextInt();

                    // 2. Citim distanțele date de Bronzarel
                    long[] given = new long[N + 1];
                    for (int i = 1; i <= N; i++) {
                        given[i] = sc.nextLong();
                    }

                    // 3. Construim lista de adiacență cu tablouri paralele
                    head = new int[N + 1];
                    Arrays.fill(head, -1);
                    to = new int[2 * M];
                    cost = new int[2 * M];
                    nxt = new int[2 * M];
                    edgeCnt = 0;

                    // 4. Citim muchiile și le adăugăm bidirecțional (graf neorientat)
                    for (int i = 0; i < M; i++) {
                        int u = sc.nextInt(), v = sc.nextInt(), c = sc.nextInt();
                        addEdge(u, v, c);
                        addEdge(v, u, c);
                    }

                    // 5. Calculăm distanțele cu Dijkstra
                    long[] dist = dijkstra();

                    // 6. Verificăm dacă sunt corecte
                    boolean ok = true;
                    for (int i = 1; i <= N; i++) {
                        long di = dist[i] >= INF / 2 ? -1 : dist[i];
                        if (di != given[i]) {
                            ok = false;
                            break;
                        }
                    }

                    // 7. Adăugăm rezultatul în listă
                    if (ok) {
                        results.add("DA");
                    } else {
                        results.add("NU");
                    }
                }
                sc.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        /* ============================ Scriere ============================ */
        private void writeOutput() {
            try {
                BufferedWriter bw = new BufferedWriter(new FileWriter(OUTPUT_FILE));
                for (String line : results) {
                    bw.write(line);
                    bw.newLine();
                }
                bw.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        /* ============================ Adăugare muchii ============================ */
        static void addEdge(int u, int v, int w) {
            to[edgeCnt] = v;
            cost[edgeCnt] = w;
            nxt[edgeCnt] = head[u];
            head[u] = edgeCnt++;
        }

        /* ============================ Algoritmul Dijkstra ============================ */
        static long[] dijkstra() {
            long[] dist = new long[N + 1];
            Arrays.fill(dist, INF); // inițial toate distanțele sunt "infinite"
            dist[S] = 0;

            int[] heap = new int[N + 1];
            int[] pos = new int[N + 1];
            int heapSize = 1;
            heap[1] = S;
            pos[S] = 1;

            // Bucla principală Dijkstra
            while (heapSize > 0) {
                int u = heap[1];
                pos[u] = 0;
                heap[1] = heap[heapSize];
                pos[heap[1]] = 1;
                heapSize--;
                heapifyDown(heap, pos, dist, heapSize, 1);

                // Relaxăm muchiile lui u
                for (int e = head[u]; e != -1; e = nxt[e]) {
                    int v = to[e];
                    long nd = dist[u] + cost[e];
                    if (nd < dist[v]) {
                        dist[v] = nd;
                        if (pos[v] == 0) {
                            heapSize++;
                            heap[heapSize] = v;
                            pos[v] = heapSize;
                            heapifyUp(heap, pos, dist, heapSize);
                        } else {
                            heapifyUp(heap, pos, dist, pos[v]);
                        }
                    }
                }
            }
            return dist;
        }

        /* ============================ Heapify pentru Min-Heap ============================ */
        static void heapifyUp(int[] heap, int[] pos, long[] dist, int i) {
            while (i > 1) {
                int p = i >>> 1;
                if (dist[heap[p]] <= dist[heap[i]]) break;
                swap(heap, pos, p, i);
                i = p;
            }
        }

        static void heapifyDown(int[] heap, int[] pos, long[] dist, int heapSize, int i) {
            while (true) {
                int l = i << 1;
                int r = l | 1;
                int smallest = i;
                if (l <= heapSize && dist[heap[l]] < dist[heap[smallest]]) smallest = l;
                if (r <= heapSize && dist[heap[r]] < dist[heap[smallest]]) smallest = r;
                if (smallest == i) break;
                swap(heap, pos, i, smallest);
                i = smallest;
            }
        }

        static void swap(int[] heap, int[] pos, int i, int j) {
            int vi = heap[i], vj = heap[j];
            heap[i] = vj;
            heap[j] = vi;
            pos[vi] = j;
            pos[vj] = i;
        }
    }

    public static void main(String[] args) {
        new Task().solve();
    }
}