题目大意:给定无向图,求所有从s到t的路径中最大边与最小边的比值的最小值
题解:枚举最小边,并查集维护。
我的收获:因为ans只与路径中的边权max和min有关,是双变量优化问题。用常用的枚举其中一个变量的方法就可以通过了
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int M=505;
int n,m,st,ed,mx;
int ans_mi=1,ans_mx=12345;
int f[M*10];
struct edge{int u,v,vl;}e[M*10];
int fid(int x){return f[x]==x?x:f[x]=fid(f[x]);}
bool cmp(edge x,edge y){return x.vl<y.vl;}
void uniom(int u,int v){
int x=fid(u),y=fid(v);
if(x!=y) f[x]=y;
}
bool kruskal(int x)
{
mx=-1;
for(int i=1;i<=m;i++) f[i]=i;
for(int i=1;i<=m;i++)
{
if(fid(st)==fid(ed)) break;
//s可以到达t,此时的mx即为最大边权
if(e[i].vl<x) continue;//x为最小边权值,只能选比x大的
uniom(e[i].u,e[i].v);
mx=e[i].vl;
}
if(fid(st)==fid(ed)) return true;
return false;
}
void del(int x)
{
if(!kruskal(x)) return ;
if(double(mx)/x<double(ans_mx)/ans_mi)//double/int会变成double
ans_mx=mx,ans_mi=x;
int key=__gcd(ans_mx,ans_mi);//有爱的函数
ans_mx/=key,ans_mi/=key;
}
void work()
{
for(int i=1;i<=m;i++)//枚举最小边
del(e[i].vl);
if(ans_mx==12345) puts("IMPOSSIBLE");//无解
else if(ans_mi==1) printf("%d\n",ans_mx);
else printf("%d/%d\n",ans_mx,ans_mi);
}
void init()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].vl);
sort(e+1,e+1+m,cmp);
cin>>st>>ed;
}
int main()
{
init();
work();
return 0;
}