洛谷 P2502 [HAOI2006]旅行

题目描述

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

输入输出格式

输入格式:
第一行包含两个正整数,N和M。

接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。

最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。

输出格式:
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

输入输出样例

输入样例#1:
4 2
1 2 1
3 4 2
1 4
输出样例#1:
IMPOSSIBLE
输入样例#2:
3 3
1 2 10
1 2 5
2 3 8
1 3
输出样例#2:
5/4
输入样例#3:
3 2
1 2 2
2 3 4
1 3
输出样例#3:
2
说明

【数据范围】

1小于N≤500

1≤x,y≤N,0小于v小于30000,x≠y

0小于M≤5000

排序+并查集:
1.把速度排序。
2.大到小枚举。
3.以每一个景点为中心开始做并查集,依次加入边,直到s与t联通或者最后无法联通,如果联通,则与之前的答案对比,然后决定替换。
4.因为速度已经按顺序排序了,所以一旦有一个无法构成并查集,就直接退出。
5.判断是否无解,有解的话要注意约分。

时间复杂度:O(m^2)

var
   x,y,v:array [0..5001] of longint;
   f:array [0..501] of longint;
   s,t,p,q,min,max,i,j,n,m:longint;

procedure qsort(l,r:longint);
var
   i,j,mid,t:longint;
begin
    if l>=r then exit;
    i:=l; j:=r;
    mid:=v[(l+r) div 2];
       repeat
            while v[i]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;
    qsort(i,r);
    qsort(l,j);
end;

function find(a:longint):longint;
begin
    if f[a]=a then exit(a);
    f[a]:=find(f[a]);
    exit(f[a]);
end;

function gys(ab,xy:longint):longint;
begin
    if xy=0 then exit(ab)
            else gys:=gys(xy,ab mod xy);
end;

begin
    readln(n,m);
    for i:=1 to m do readln(x[i],y[i],v[i]);
    readln(s,t);
    qsort(1,m);
    min:=1; max:=50000;
    for i:=1 to m do
        begin
           for j:=1 to n do f[j]:=j;
           j:=i-1;
           p:=v[i];
           while (j<=m) and (find(s)<>find(t)) do
                 begin
                      inc(j);
                      f[find(x[j])]:=f[find(y[j])];
                      q:=v[j];
                 end;
           if find(s)<>find(t) then break;
           if q/pthen
              begin
                   min:=p;
                   max:=q;
              end;
        end;
    if max=50000
       then writeln('IMPOSSIBLE')
       else begin
                p:=gys(max,min);
                if max mod min=0 then writeln(max div min)
                                 else writeln(max div p,'/',min div p);
            end;
end.

你可能感兴趣的:(并查集,pascal,排序&拓扑,暴力/枚举/模拟)