Description
给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求
一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个
比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。
Input
第一行包含两个正整数,N和M。下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路
,车辆必须以速度v在该公路上行驶。最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比
最小的路径。s和t不可能相同。
1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000
Output
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。
如果需要,输出一个既约分数。
Sample Input
【样例输入1】
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3
Sample Output
【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
Solution
先将边排序,然后枚举最小边,用Kruskal的方法加边然后判断s,t是否连通。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,m,S,T,ansx,ansy,f[505]; struct node{int u,v,val;}a[5005]; double ans; bool cmp(node a,node b) { return a.val<b.val;} int gcd(int x,int y) { if (y==0) return x;else return gcd(y,x%y); } int get(int x) { if (f[x]==x) return x;else f[x]=get(f[x]); return f[x]; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].val); scanf("%d%d",&S,&T); sort(a+1,a+m+1,cmp); ans=1<<29; for (int i=1;i<=m;i++) if (a[i].val!=a[i-1].val) { for (int j=1;j<=n;j++) f[j]=j; for (int j=i;j<=m;j++) { int x1=get(a[j].u),y1=get(a[j].v); if (x1!=y1) f[x1]=y1; if (get(S)==get(T)) { if ((double)a[j].val/(double)a[i].val<ans) { ansx=a[j].val;ansy=a[i].val; ans=(double)a[j].val/(double)a[i].val; } break; } } } if (ans==1<<29) { printf("IMPOSSIBLE\n");return 0;} int z=gcd(ansx,ansy); if (ansy==z) { printf("%d\n",ansx/z);return 0;} printf("%d/%d\n",ansx/z,ansy/z); return 0; } |
良心三数据
居然还有LCT维护最小生成树的做法%