1 条题解

  • 0
    @ 2026-8-5 0:02:29

    首先一定需要考虑 roger 走到里 student 需要走到的距离最长的点。

    但是,我们会发现有些点 roger 是走不到的。

    只能再跑一个最短路进行判断 roger 是否可以走到某个点。

    我们可以枚举 roger 可以走的点。

    然后对这个点所连的边进行处理就行了。

    大致思路就是这样。

    那么我们应该如何处理呢?

    下面有几种情况:

    • roger 停下来,等 student 抓 roger。
    • roger 与 student 相遇。
    • roger 与 student 形成追及。

    可以知道的是,若 v1v2v_1 \ge v_2,roger 和 student 是无法成为第 33 种情况的。

    我们先处理前两种情况。

    先定义一下,roger 走到 uu 的时间为 rouro_u,student 走到 uuvv 的时间分别是 stust_ustvst_vuuvv 的路程是 ww

    肯定,最优的情况是当 stu+x=stv+wxst_u + x = st_v + w - x ,化简得到 x=stv+wstu2x = \frac{st_v+w-st_u}{2},所以 student 所走的总路程就是 stu+xst_u + x,也就是 stv+w+stu2\frac{st_v+w+st_u}{2},那么时间就是 stv+w+stu2v2\frac{st_v+w+st_u}{2v_2}

    然后再处理第 33 种情况。

    很轻松的可以得出:

    $$(\frac{st_u}{v_2} - \frac{ro_u}{v_1}) \times v_1 + tv_1 = tv_2$$

    稍微解释一下,因为 roger 是提前到达的,所以需要乘上比 student 先到达的时间,右面两项就很显然了。

    我们解出来就是 t=stuv1rouv2v2(v2v1)t = \frac{st_uv_1 - ro_uv_2}{v_2(v_2-v_1)}

    然后我们把 tt 加上 student 到达 uu 的时间就是答案了。

    得到的是 sturouv2v1\frac{st_u-ro_u}{v_2-v_1}

    现在只需要和上面相遇取一个最小值就是答案。

    然后就做完了。

    代码有点丑,谅解一下~

    #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
    上传者