(ssl1312)P2502 2006河南省赛第一试 旅行

2006河南省赛第一试 旅行

Time Limit:2000MS

Memory Limit:65536K

Total Submit:155

Accepted:57

Description

  Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。

Input

第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。
最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。

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

Hint

【数据范围】
1<N<=500
1<=x,y<=N,0<v<30000,x≠y
0<M<=5000

Source

elba
   题解:本题是并查集(并查集详见:这里)`
      本题思路为先快排(题目要求最小比),再去合并(本次不需要压缩路径),最后再用个循环去找最小比。
      不过输出时有要求用分数,所以要化简,便需要辗转相除法。

var
 x,y,v,f:array[0..5000]of longint;
 n,m,s,t,i,j,min,max,d:longint;
procedure kp(l,r:longint);//快排
var
 i,j,mid:longint;
begin
 i:=l; j:=r;
 mid:=v[(l+r)div 2];
 repeat
  while v[i]<mid do inc(i);
  while v[j]>mid do dec(j);
  if i<=j then
   begin
    x[0]:=x[i]; x[i]:=x[j]; x[j]:=x[0];
    y[0]:=y[i]; y[i]:=y[j]; y[j]:=y[0];
    v[0]:=v[i]; v[i]:=v[j]; v[j]:=v[0];
    inc(i); dec(j);
   end;
 until i>j;
 if l<j then kp(l,j);
 if i<r then kp(i,r);
end;
function find(a:longint):longint;//找爸爸(笑~)
begin
 if f[a]<0 then exit(a)
           else
            begin
             f[a]:=find(f[a]);
             exit(f[a])
            end;
end;
procedure fusion(a,b:longint);//合并
var
 x,y:longint;
begin
 x:=find(a); y:=find(b);
 if x<>y then
          begin
           f[x]:=f[x]+f[y];
           f[y]:=x;
          end;
end;
function chu(a,b:longint):longint;//辗转相除法
begin
 if b=0 then exit(a)
        else chu:=chu(b,a mod b);
end;
begin
 read(n,m);
 for i:=1 to m do read(x[i],y[i],v[i]);
 read(s,t);
 kp(1,m);
 max:=v[m]+1; min:=v[1];//最大比啦
 for i:=1 to m do//慢慢地枚举,直到找到最小比
  begin
   fillchar(f,sizeof(f),$ff);
   j:=i-1;
   while (j<m) and (find(s)<>find(t)) do//没超出范围,而且不是同一集合就合并
    begin
     inc(j);
     fusion(x[j],y[j]);
    end;
   if find(s)<>find(t) then break;//还不是就是去不了了(排除程序自身错误)
   if v[j]*min<v[i]*max then begin max:=v[j]; min:=v[i]; end;//找最小比
  end;
 if max*v[1]>min*v[m] then writeln('IMPOSSIBLE')//没有路径
                      else
                       begin
                        d:=chu(min,max);//最大公因数
                        max:=max div d;//化简
                        min:=min div d;
                        if max mod min=0 then writeln(max div min)
                                         else writeln(max,'/',min);
                       end;
end.
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值