[HAOI2006] 旅行

求一张无向图最大边权与最小边权之比最小的 (s o t) 路径,(nleq 500,m leq 5000)

Solution

考虑枚举最小权边,然后按照 (Kruskal) 算法的思想,从小到大枚举边,看什么时候 (s,t) 连通就退出

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 10005;

struct frac {
    int x,y;
    void simp() {
        int g=__gcd(x,y);
        x/=g; y/=g;
    }
    void print() {
        if(y==1) cout<<x<<endl;
        else cout<<x<<"/"<<y<<endl;
    }
    bool operator < (const frac &b) {
        return x*b.y < y*b.x;
    }
};

struct edge {
    int u,v,w;
    bool operator < (const edge &b) {
        return w<b.w;
    }
} e[N];
int n,m,s,t,t1,t2,t3;

int fa[N];
void reset() {
    for(int i=1;i<=n;i++) fa[i]=i;
}
int find(int p) {
    return fa[p]==p?p:fa[p]=find(fa[p]);
}
void merge(int p,int q) {
    p=find(p);
    q=find(q);
    if(p-q) fa[p]=q;
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=m;i++) {
        cin>>e[i].u>>e[i].v>>e[i].w;
    }
    cin>>s>>t;
    sort(e+1,e+m+1);
    frac ans=(frac){(int)2e9,1};
    for(int i=1;i<=m;i++) {
        reset();
        for(int j=i;j<=m;j++) {
            merge(e[j].u,e[j].v);
            if(find(s)==find(t)) {
                if((frac){e[j].w,e[i].w}<ans)
                    ans=(frac){e[j].w,e[i].w};
                break;
            }
        }
    }
    if((frac){(int)1e9,1}<ans) cout<<"IMPOSSIBLE"<<endl;
    else ans.simp(),ans.print();
}

原文地址:https://www.cnblogs.com/mollnn/p/12384730.html