求一张无向图最大边权与最小边权之比最小的 (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();
}