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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值