旅行 纪中2547 并查集+枚举

    xiaoxiao2024-04-22  4

    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”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

    数据范围

    对于100%的数据,1 < N≤500,1≤x,y≤N,0<M<5000

    分析

    因为数据范围比较小,m*m不会爆,所以我们可以枚举最大最小的边。 先按边权从小到大排序,枚举最小边 然后把其他边从小到大加入,把这些边连接的点放入一个集合(并差集) 每加入一条边,就判断s和t是否在一个集合。是的话就是一种可行解。

    代码

    type arr=record x,y,w:longint; next:longint; end; var a:array[1..50000] of arr; ls:array[1..5000] of longint; f:array[1..5000] of longint; s,t:longint; num:longint; ans:real; n,m:longint; head,tail:longint; i,j,k,z:longint; function find(v:longint):longint; begin if f[v]=v then exit(v) else begin f[v]:=find(f[v]); find:=f[v]; end; end; procedure union(x,y:longint); var i,j,k:longint; begin i:=find(x); j:=find(y); f[i]:=j; end; procedure qsort(l,r:longint); var i,j,k:longint; mid:longint; temp:arr; begin if l>=r then exit; i:=l; j:=r; mid:=a[(l+r) div 2].w; repeat while a[i].w<mid do i:=i+1; while a[j].w>mid do j:=j-1; if i<=j then begin temp:=a[i]; a[i]:=a[j]; a[j]:=temp; i:=i+1; j:=j-1; end; until i>j; qsort(l,j); qsort(i,r); end; procedure c(x,y:longint); var i,j,k:longint; begin i:=x; j:=y; while j<>0 do begin k:=i mod j; i:=j; j:=k; end; x:=x div i; y:=y div i; if x mod y=0 then write(x div y) else write(x,'/',y); end; procedure add(x,y,w:longint); begin num:=num+1; a[num].x:=x; a[num].y:=y; a[num].w:=w; a[num].next:=ls[x]; ls[x]:=num; end; begin readln(n,m); for i:=1 to m do begin readln(j,k,z); add(j,k,z); end; read(s,t); qsort(1,num); ans:=maxlongint; head:=0; tail:=0; for i:=1 to num do begin for j:=1 to n do f[j]:=j; for j:=i to num+1 do begin if find(s)=find(t) then break; if j>num then break; union(a[j].x,a[j].y); end; j:=j-1; if (a[j].w/a[i].w<ans) and (find(s)=find(t)) then begin ans:=a[j].w/a[i].w; head:=a[j].w; tail:=a[i].w; end; end; if (head=0) and (tail=0) then write('IMPOSSIBLE') else c(head,tail); end.
    转载请注明原文地址: https://ju.6miu.com/read-1288253.html
    最新回复(0)