Description
给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求
一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个
比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。
解:
题目要求一条s-->t的路径满足最大值和最小值之间的比例最小。
1、想到枚举最大值找最小值最大or 枚举最小值找最大值最小
2、对边排序,枚举最大边,跑最大生成树,求出比值里最小的
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define en '\n'
const int maxn =5e3+10;
const int inf=0x3f3f3f3f;
inline int read(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,m,s,t;
struct node{
ll x,y,w;
bool operator <(const node &b)const{
return w<b.w;
}
}edge[maxn];
bool v[maxn];
int f[maxn];
ll gcd(ll a,ll b){
if(b==0)return a;return gcd(b,a%b);
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
signed main()
{
#ifdef local
freopen("input2.txt","r",stdin);
#endif
#define int register int
n=read(),m=read();
for(int i=1;i<=m;i++)edge[i].x=read(),edge[i].y=read(),edge[i].w=read();
sort(edge+1,edge+1+m);s=read(),t=read();
ll x=1,y=inf;bool yes=0;ll mx,mi;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)f[j]=j;
mx=edge[i].w;
for(int j=i;j>=1;--j){
int xx=find(edge[j].x),yy=find(edge[j].y);
if(xx==yy)continue;f[xx]=yy;
mi=edge[j].w;
if(find(s)==find(t)){yes=1;
if(y*mi>x*mx){
int tem=gcd(mx,mi);
y=mx/tem;x=mi/tem;
}
break;
}
}
}
if(!yes)puts("IMPOSSIBLE");
else {
if(x==1)cout<<y<<en;
else
cout<<y<<'/'<<x<<en;
}
return 0;
}