1 条题解
-
0
首先一定需要考虑 roger 走到里 student 需要走到的距离最长的点。
但是,我们会发现有些点 roger 是走不到的。
只能再跑一个最短路进行判断 roger 是否可以走到某个点。
我们可以枚举 roger 可以走的点。
然后对这个点所连的边进行处理就行了。
大致思路就是这样。
那么我们应该如何处理呢?
下面有几种情况:
- roger 停下来,等 student 抓 roger。
- roger 与 student 相遇。
- roger 与 student 形成追及。
可以知道的是,若 ,roger 和 student 是无法成为第 种情况的。
我们先处理前两种情况。

先定义一下,roger 走到 的时间为 ,student 走到 和 的时间分别是 和 , 和 的路程是 。
肯定,最优的情况是当 ,化简得到 ,所以 student 所走的总路程就是 ,也就是 ,那么时间就是 。
然后再处理第 种情况。
很轻松的可以得出:
$$(\frac{st_u}{v_2} - \frac{ro_u}{v_1}) \times v_1 + tv_1 = tv_2$$稍微解释一下,因为 roger 是提前到达的,所以需要乘上比 student 先到达的时间,右面两项就很显然了。
我们解出来就是 。
然后我们把 加上 student 到达 的时间就是答案了。
得到的是 。
现在只需要和上面相遇取一个最小值就是答案。
然后就做完了。
代码有点丑,谅解一下~
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 2e3+10; const int M = 1e4+10; const int inf = 0x3f3f3f3f3f3f3f3f; struct node { int a, dis; }; bool operator<(node x, node y) { return x.dis > y.dis; } int n, m, v1, v2; int cost[M]; int cnt, head[N]; int nxt[M], to[M]; void connect(int u, int v, int w) { cnt++, cost[cnt] = w, to[cnt] = v; nxt[cnt] = head[u], head[u] = cnt; } int dstu[N], dro[N]; priority_queue<node> q; int pos[N]; void student(int x) { memset(dstu, 0x3f, sizeof dstu); dstu[x] = 0; q.push({x, 0}); while (!q.empty()) { int u = q.top().a, d = q.top().dis; q.pop(); if (dstu[u] < d) continue; for (int i = head[u];i;i=nxt[i]) { int v = to[i], w = cost[i]; if (dstu[v] > dstu[u] + w) { dstu[v] = dstu[u] + w; q.push({v, dstu[v]}); } } } } bool comp(int x, int a, int y, int b) { if (x * b > y * a) return 1; return 0; } void roger(int x) { memset(dro, 0x3f, sizeof dro); dro[x] = 0; q.push({x, 0}); while (!q.empty()) { int u = q.top().a, d = q.top().dis; q.pop(); if (dro[u] < d) continue; for (int i = head[u];i;i=nxt[i]) { int v = to[i], w = cost[i]; if (comp(dstu[v], v2, dro[u]+w, v1)) { if (dro[v] > dro[u] + w) { dro[v] = dro[u] + w; q.push({v, dro[v]}); } } } } } void cmax(int &x, int &y, int a, int b) { if (x * b < a * y) x = a, y = b; } bool kmin(int x, int y, int a, int b) { if (x * b > a * y) return 1; else return 0; } signed main() { cin >> n >> m >> v1 >> v2; int u, v, w; for (int i = 1;i<= m;i++) { cin >> u >> v >> w; connect(u, v, w); connect(v, u, w); } int cur = 0; for (int i = 2;i<= n;i++) { student(i); roger(1); int uout = 0, dout = 1; for (int j = 1;j<= n;j++) { if (dro[j] >= inf) continue; int Smin = dstu[j]; cmax(uout, dout, dstu[j], v2); if (v1 < v2) { for (int k = head[j];k;k=nxt[k]) { int v = to[k], w = cost[k]; if (kmin(dstu[j] + dstu[v] + w, 2 * v2, dstu[j] - dro[j], v2-v1)) cmax(uout, dout, dstu[j]-dro[j], v2-v1); else cmax(uout, dout, dstu[j] + dstu[v] + w, 2 * v2); } } else { for (int k = head[j];k;k=nxt[k]) { int v = to[k], w = cost[k]; cmax(uout, dout, dstu[j] + dstu[v] + w, 2 * v2); } } } cout << uout / __gcd(uout, dout) << "/" << dout / __gcd(uout, dout) << endl; } return 0; }
- 1
信息
- ID
- 12588
- 时间
- 4000ms
- 内存
- 600MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者