http://wikioi.com/problem/1001/
问题是求最大速度和最小速度的比(边权),用最小生成树(第一加的即为最大,最后的即为最小)。然后我们就可以用枚举出每种最小生成树(这里应该可以优化)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
int n,m;
int k=1;
int s,t;
int fa[500+10];
double ans=99999.99;
int maxn=0,minn=0;
struct egde
{
int u,v,w;
friend bool operator<(egde a,egde b)
{
return a.w>b.w;
}
}e[5000*2+10];
void read()//建边
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
e[k].u=a;
e[k].v=b;
e[k].w=c;
k++;
e[k].u=b;
e[k].v=a;
e[k].w=c;
k++;
}
scanf("%d%d",&s,&t);
}
int gcd(int a,int b)
{
int t;
while(b!=0)
{
t=a;
a=b;
b=t%b;
}
return a;
}
int find(int x)
{
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]);
}
void work()//并查集
{
sort(e+1,e+k);
for(int i=1;i<k;i++)
{
for(int l=1;l<=n;l++)fa[l]=l;
fa[e[k].u]=e[k].v;
for(int j=i+1;j<k;j++)//从第J条边开始枚举
{
int fx=find(e[j].u);
int fy=find(e[j].v);
if(fx!=fy)fa[fx]=fy;
if(find(s)==find(t))
{
if(e[i].w*1.0/e[j].w<ans)//更新答案
{
maxn=e[i].w;
minn=e[j].w;
ans=maxn*1.0/minn;
}
break;
}
}
}
}
void print()//找最简
{
if(maxn==0)printf("IMPOSSIBLE\n");
else{
int d=gcd(maxn,minn);
if(maxn%minn==0)
{
printf("%d\n",maxn/minn);
}
else
{
maxn=maxn/d;
minn=minn/d;
printf("%d/%d\n",maxn,minn);
}
}
}
int main()
{
read();
work();
print();
}