旅行
题目
题目
看到M<=5000,我们应该反应过来
**O(M2)**可以AC
O(M2)应该联想到枚举区间,考虑暴力
首先sort一遍
可以证明最终连上的路一定是一个区间(中间的就算用不上,也不花钱,肯定造)
暴力枚举区间,用并查集判断连通块即可
双倍经验
既约分数比较好弄,用gcd就可以了
code:
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
double minn=2147483647;
bool ok;
struct f
{
int x,y,w;
}a[5010];
bool cmp(f x,f y)
{
return x.w<y.w;
}
int n,m,s,t,fa[510],ff,ss,k;
int find(int dep)
{
if(fa[dep]==dep)return dep;
return fa[dep]=find(fa[dep]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
scanf("%d%d",&s,&t);
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)fa[j]=j;
ok=0;
k=i;
while(k<=m)
{
fa[find(a[k].x)]=find(a[k].y);
if(find(s)==find(t))
{
ok=1;
break;
}
++k;
}
if(ok&&minn>a[k].w*1.0/a[i].w)
{
minn=a[k].w*1.0/a[i].w;
ff=a[k].w;
ss=a[i].w;
}
}
if(minn!=2147483647)
{
if(ff%ss==0)printf("%d",ff/ss);
else printf("%d/%d",ff/__gcd(ff,ss),ss/__gcd(ff,ss));
}
else printf("IMPOSSIBLE");
return 0;
}