【bzoj 1050】 旅行comf 【HAOI2006】

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章