G. Moving Platforms
G. Moving Platforms
There is a game where you need to move through a labyrinth. The labyrinth consists of platforms, connected by passages.
Each platform is at some level , an integer number from to . In a single step, if you are currently on platform , you can stay on it, or move to another platform . To move to platform they have to be connected by the passage, and their levels have to be the same, namely .
After each step, the levels of all platforms change. The new level of platform is calculated as , for all .
You start on platform . Find the minimum number of steps you need to get to platform .
Input
The first line of input contains a single integer () — the number of test cases. Then the descriptions of the test cases follow.
The first line of each test case contains three integers , , and (, , ).
The second line contains integers , the initial level of each platform ().
The third line contains integers , the change of level for each platform ().
Next lines contain a description of the passages. Each passage is described as a pair of integers — the platforms, connected by the passage. There is at most one passage connecting each pair of platforms, and there is no passage connecting a platform to itself.
The sum of for all tests does not exceed , the sum of for all tests does not exceed .
Output
For each test case, print a single integer, the minimum number of steps needed to get from platform to platform .
If it is impossible to get to platform , print .
Example
input
3
3 3 10
1 9 4
2 3 0
1 2
3 2
1 3
2 1 10
1 2
4 6
1 2
8 7 25
22 14 5 3 10 14 11 1
9 5 4 10 7 16 18 18
2 8
6 3
3 5
7 5
2 6
1 4
4 7
output
6
-1
52
Note
This is how levels of the platforms change, and what actions we need to perform in the first example.
Platform 1 | Platform 2 | Platform 3 | Action | |
Step 1 | 1 | 9 | 4 | Stay on the platform 1 |
Step 2 | 3 | 2 | 4 | Stay on the platform 1 |
Step 3 | 5 | 5 | 4 | Move to the platform 2 |
Step 4 | 7 | 8 | 4 | Stay on the platform 2 |
Step 5 | 9 | 1 | 4 | Stay on the platform 2 |
Step 6 | 1 | 4 | 4 | Move to the platform 3 |
解题思路
前置知识:扩展欧几里得算法用于求解 的可行解。对于任意方程 存在可行解的充要条件是 ,如果有解则先通过 exgcd 求出 的一组可行解 和 ,那么 与 就是 的一组可行解。得到可行解后就可以构造通解 ,其中 。
相邻两点 和 只有在高度相同时的时刻才能从 走到 ,假设到达 的时刻为 ,现在要求满足 且大于等于 的最小时刻 。该同余方程等价于 , 相当于 , 相当于 , 相当于 。为了方便如果 ,则令 ,即把 变成模 意义下最小的非负整数,同余方程仍然成立,同理 和 。
令 ,先求出 的可行解 ,那么 就是 的可行解,令 ,那么 就是通解。接着求满足 的最小 ,如果 那么直接有 。否则如果 ,那么需要 ,等价于 , 取等号即可,则 。同理如果 ,那么需要 ,等价于 , 取等号,则 。
以上就是求每个相邻节点边权的做法,然后就可以用 Dijkstra 跑最短路了。简单证明一下正确性,假设当前未标记的节点中 最小,那么不可能再通过其他未标记的节点 来更新使得 变小,因为 而从 到 的最小时刻 ,所以与一般的 Dijkstra 一样标记 并更新其他未标记节点的最小值即可。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10, M = N * 2;
int h[N], e[M], ne[M], idx;
int a[N], b[N];
LL dist[N];
bool vis[N];
void add(int u, int v) {
e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}
int exgcd(int a, int b, int &x, int &y) {
if (!b) {
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
void solve() {
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
for (int i = 1; i <= n; i++) {
scanf("%d", b + i);
}
memset(h, -1, n + 10 << 2);
idx = 0;
while (m--) {
int u, v;
scanf("%d %d", &u, &v);
add(u, v), add(v, u);
}
priority_queue<array<LL, 2>> pq;
pq.push({0, 1});
memset(dist, 0x3f, n + 10 << 3);
dist[1] = 0;
memset(vis, 0, n + 10);
while (!pq.empty()) {
auto p = pq.top();
pq.pop();
if (vis[p[1]]) continue;
vis[p[1]] = true;
for (int i = h[p[1]]; i != -1; i = ne[i]) {
int x, y;
int d = exgcd((b[p[1]] - b[e[i]] + k) % k, k, x, y);
if ((a[e[i]] - a[p[1]]) % d) continue;
LL t = LL(a[e[i]] - a[p[1]] + k) % k / d * x;
LL z = k / d;
if (t > -p[0]) t -= (t + p[0]) / z * z;
else if (t < -p[0]) t += (-p[0] - t + z - 1) / z * z;
if (dist[e[i]] > t + 1) {
dist[e[i]] = t + 1;
pq.push({-t - 1, e[i]});
}
}
}
printf("%lld\n", dist[n] == 0x3f3f3f3f3f3f3f3f ? -1 : dist[n]);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round 927 (Div. 3) A-G:https://zhuanlan.zhihu.com/p/682734505
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18022870
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-02-20 构造新矩阵