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
Sample Output
【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
对于这道题,首先对边按边权排序,然后枚举最小边,按边权依次加边,用并查集维护s到t的连通性,当s与t连通时,更新答案即可,下面是程序:
#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=505;
int f[N];
struct edge{
int u,v,w;
bool operator<(const edge &p)const{
return w<p.w;
}
}e[5005];
int findf(int u){
return f[u]=u==f[u]?u:findf(f[u]);
}
int gcd(int a,int b){
int t;
while(b){
t=a%b;
a=b;
b=t;
}
return a;
}
int main(){
int i,j,n,m,s,t,x,y,fm,fz;
bool flag;
double mn=0x7fffffff;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
scanf("%d%d",&s,&t);
sort(e+1,e+m+1);
for(i=1;i<=m;i++){
flag=0;
for(j=1;j<=n;j++){
f[j]=j;
}
for(j=i;j<=m;j++){
x=findf(e[j].u),y=findf(e[j].v);
if(x!=y){
f[x]=y;
}
if(findf(s)==findf(t)){
flag=1;
break;
}
}
if(flag){
double tp=e[j].w*1.0/e[i].w;
if(tp<mn){
mn=tp;
fz=e[j].w;
fm=e[i].w;
}
}
}
if(mn==0x7fffffff){
puts("IMPOSSIBLE");
}
else{
t=gcd(fz,fm);
fz/=t;
fm/=t;
if(fm==1){
printf("%d\n",fz);
}
else{
printf("%d/%d",fz,fm);
}
}
return 0;
}