P2502题解

传送门:https://www.luogu.com.cn/problem/P2502

要同时考虑最大值和最小值,我们先将边权排序。然后我们枚举最小边,构建出恰使 \(s\)\(t\) 联通的最小生成树。如果可行则与当前方案比较,我们发现即使枚举的边和构建出的生成树的最大边路径不在同一条路径上,我们在下一轮也会丢弃这一条最小边,所以只需要枚举最小边,丢弃更小边的同时找到恰好能使 \(s\)\(t\) 联通最小的最大边即可,整个过程类似于 \(Krusal\) 最小生成树算法,过程用并查集维护即可。

#include <bits/stdc++.h>

using namespace std;

struct Edge {
    int u, v, w;

    bool operator <(const Edge &e) const {
        return w < e.w;
    }
} e[5001];

int fa[501], x, y;

double ans;

int get(int x) { return x == fa[x] ? x : fa[x] = get(fa[x]); }

int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, m, s, t;
    cin >> n >> m;
    for (int i = 1; i <= m; ++i) cin >> e[i].u >> e[i].v >> e[i].w;
    sort(e + 1, e + m + 1);
    cin >> s >> t;
    ans = 3e4;
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) fa[j] = j;
        for (int j = i; j <= m; ++j) {
            if (get(e[j].u) != get(e[j].v)) fa[get(e[j].u)] = get(e[j].v);
            if (get(s) == get(t)) {
                if (1.0 * e[j].w / e[i].w < ans)
                    ans = 1.0 * e[j].w / e[i].w, x = e[j].w / gcd(e[i].w, e[j].w), y = e[i].w / gcd(e[i].w, e[j].w);
                break;
            }
        }
    }
    if (ans == 3e4) {
        cout << "IMPOSSIBLE";
        return 0;
    }
    cout << x;
    if (y != 1) cout << "/" << y;
    return 0;
}
posted @ 2025-07-15 17:58  Jefferyzzzz  阅读(7)  评论(0)    收藏  举报