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;
}