Codeforces Round 927 (Div. 3) G. Moving Platforms --- 题解 (非常好的题)

文章讲述了在Codeforces竞赛中的一道题目,涉及如何在给定的城市网络中,利用模运算计算在满足条件下的最短时间路径,以便从第一个城市到达最后一个城市。主要讨论了思路解析和代码实现,涉及到最短路径算法和模运算的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

Codeforces Round 927 (Div. 3) G. Moving Platforms:

原题链接:Problem - G - Codeforces

题目大意:

思路解析:

代码实现:


Codeforces Round 927 (Div. 3) G. Moving Platforms:

原题链接:Problem - G - Codeforces

题目大意:

        给你n个城市,m条道路,组成一个无向图,给你一个模数h,每个城市有一个初始价值为si,并且每个城市在每秒会有一个变化值li,当 (si+ t * li) mod h == (sj + t * lj) mod h时通道才会打开,问从第一个城市到最后一个城市最少需要多少时间,如果无法到达输出-1.

思路解析:

        给你n个城市,m条道路,组成一个无向图,问从第一个城市到最后一个城市最少需要多少时间这里很容易可以想到需要用到最短路,但是在跑最短路时我们怎么判断当前两个城市是否能够进行转移,或者转移需要等待多长时间,便成了主要难点。

        

        

代码实现:

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

public class Main {
    public static void main(String[] args) throws IOException {
        int T = input.nextInt();
        for (int o = 0; o < T; o++) {
            int n = input.nextInt();
            int m = input.nextInt();
            int H = input.nextInt();
            Vector<Integer> g[] = new Vector[n];
            for (int i = 0; i < n; i++) {
                g[i] = new Vector<>();
            }
            PriorityQueue<Node> nodes = new PriorityQueue<Node>(new Comparator<Node>() {
                @Override
                public int compare(Node o1, Node o2) {
                    if (o1.time > o2.time) return 1;
                    else if (o1.time == o2.time) return o1.x - o2.x;
                    return -1;
                }
            });
            int[] l = new int[n+1];
            long[] s = new long[n+1];
            for (int i = 0; i < n; i++) {
                l[i] = input.nextInt();
            }
            for (int i = 0; i < n; i++) {
                s[i] = input.nextInt();
            }
            for (int i = 0; i < m; i++) {
                int x = input.nextInt() - 1;
                int y = input.nextInt() - 1;
                g[x].add(y);
                g[y].add(x);
            }
            long[] dp = new long[n];
            Arrays.fill(dp, (long) 1e18);
            dp[0] = 0;
            nodes.add(new Node(0, dp[0]));
            while (!nodes.isEmpty()){
                Node cur = nodes.poll();
                int v = cur.x;
                long t = dp[v];
                if (t < cur.time) continue; // 因为他可能里面存放了多个 u,dp[u]的点,选择当时加入时dp[u]最小的那个进行遍历即可
                for (Integer u : g[v]) {
                    long a = (l[v] + (t % H) * s[v]) - (l[u] + (t % H) * s[u]);
                    a %= H;
                    if (a < 0) a += H;
                    long b = s[u] - s[v];
                    b %= H;
                    if (b < 0) b += H;
                    // a - bx = yH
                    long[] arr = eucl(b, H);
                    long dd = arr[0];
                    long x = arr[1];
                    // xb + yH = dd
                    if (a % dd != 0) continue;
                    x *= a / dd;
                    x %= (H / dd);
                    if (x < 0) x += H / dd;
                    long dt = x;
                    if (dp[v] + dt + 1 < dp[u]){
                        dp[u] = dp[v] + dt + 1;
                        nodes.add(new Node(u, dp[u]));
                    }
                }
            }
            if (dp[n - 1] == (long) 1e18) out.println(-1);
            else out.println(dp[n - 1]);
        }
        out.flush();
        out.close();
        br.close();
    }
    public static long[] eucl(long a, long b) { // 扩展欧几里得
        if (b == 0) {
            return new long[]{a, 1, 0}; //
        }
        long k = a / b;
        long[] arr = eucl(b, a - k * b);
        return new long[]{arr[0], arr[2], arr[1] - k * arr[2]};
    }
    public static class Node{
        int x;
        long time;
        public Node(int x, long time){
            this.x = x;
            this.time = time;
        }

    }


    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    static Input input = new Input(System.in);
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static class Input {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public Input(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

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


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Studying~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值