思路:枚举速度最大的那条边,一条条插入比它速度小的边,直到两地连通——这里可以使用并查集,逐个比较比值,取最小的就行了。
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #define INF 0xfffffff #define N 5500 using namespace std; int f[N]; struct node { int x,y,v; }; int cmp(node a,node b) { return a.v<b.v; } int gcd(int m,int n) { return n?gcd(n,m%n):m; } int Find(int x) { return x==f[x]?x:f[x]=Find(f[x]); } int main() { int n,p,q,T,m,i,j,minv,maxv; node a[N]; scanf("%d",&T); while(T--) { memset(a,0,sizeof(a)); scanf("%d %d",&n,&m); for(i=1;i<=m;i++) { scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].v); } scanf("%d%d",&p,&q); sort(a+1,a+m+1,cmp); double ans=INF; for(i=m;i>=1;i--)//从最大的边开始,将比它小的边加入 { for(j=1;j<=n;j++) f[j]=j; for(j=i;j>0;j--) { int x=Find(a[j].x); int y=Find(a[j].y); if(x!=y) { f[x]=y; } else continue ; if(Find(p)==Find(q))//起点和终点在都一个集合里 break; } if(j==0)//如果把边都加进去完了,说明起点和终点不连通 break; if(a[i].v*1.0/a[j].v<ans) { ans=a[i].v*1.0/a[j].v; maxv=a[i].v; minv=a[j].v; } } if(ans==INF) printf("IMPOSSIBLE\n"); else if(maxv%minv==0) printf("%d\n",maxv/minv); else printf("%d/%d\n",maxv/gcd(maxv,minv),minv/gcd(maxv,minv)); } return 0; }