CF1932G 题解
思路
首先这题要用最短路是显然的,但是边权不固定(但对 dijkstra 过程没影响,因为边权没有负数)。在做 dijkstra 的时候,我们的边权取决于不固定的当前高度和固定的增长高度,然后类似 P1516 用 exgcd 把边权算出来松弛即可。
注意事项
请及时取模,否则在乘法和 exgcd 时会爆 long long。
代码
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
const ll inf = 1e18;
struct node {
int x;
ll dis;
bool operator < (const node& t) const {
return dis > t.dis;
}
} ;
ll exgcd (ll a, ll b, ll& x, ll& y) {
if (! b) {
x = 1, y = 0;
return a;
}
ll g = exgcd (b, a % b, x, y), tmp = x;
x = y, y = tmp - a / b * y;
return g;
}
int t, n, m, x, y;
ll h, l[100005], s[100005], dis[100005], a, b, w, ans1, ans2, g;
vector <int> v[100005];
priority_queue <node> q;
ll exg (ll a, ll b, ll c) {
if (a < 0)
a = -a, c = -c;
g = exgcd (a, b, ans1, ans2);
if (c % g)
return inf;
b /= g, c /= g;
return (ans1 * c % b + b) % b;
}
ll bfs () {
fill (dis + 2, dis + n + 1, inf);
q.push ({1, 0});
while (! q.empty ()) {
node t = q.top ();
if (t.x == n) {
while (! q.empty ())
q.pop ();
return t.dis;
}
q.pop ();
if (t.dis > dis[t.x])
continue ;
for (int& i : v[t.x]) {
w = exg (s[i] - s[t.x], h, (t.dis % h * (s[t.x] - s[i]) + l[t.x] - l[i]) % h) + 1;
if (t.dis + w < dis[i])
q.push ({i, dis[i] = t.dis + w});
}
}
return -1;
}
int main () {
ios::sync_with_stdio (0);
cin.tie (0);
cout.tie (0);
cin >> t;
while (t --) {
cin >> n >> m >> h;
for (int i = 1; i <= n; ++ i)
cin >> l[i], v[i].clear ();
for (int i = 1; i <= n; ++ i)
cin >> s[i];
while (m --) {
cin >> x >> y;
v[x].emplace_back (y);
v[y].emplace_back (x);
}
cout << bfs () << '\n';
}
return 0;
}

浙公网安备 33010602011771号