2006河南省赛第一试 旅行(并查集)

题意:

Z小镇附近共有N个景点,这些景点被M条道路连接着,所有道路都是双向的,对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。最大速度和最小速度的比尽可能小的路线。(

n<500 m<5000 v<30000)

思路

用最短路得话好像不是很好搞,反正我是没有想出怎么最短路,然后正好在学并查集。就用并查集搞了一波。
给他的边按速度排序,然后一个个枚举,找到哪一个就可以联通了,因为是排序过得,找到一个后就可以换一个起点再查,如果无法联通就可以退出了

时间复杂度

m个枚举起点,每个起点m次以下,并查集加上路径压缩也就1。所以为O(m*m);

const
 maxn=300000;
var
 f,x,y,v:array [0..maxn] of longint;
 i,j,k,n,m,x1,y1,p,q,max,min:longint;

function gcd(x,y:longint):longint;
var
 i,p:longint;
begin
 p:=x;
 if p>y then p:=y;
 for i:=p downto 1 do
  if (x mod i=0) and (y mod i=0) then exit(i);
end;

procedure qsort(l,r:longint);
var
 i,j,mid:longint;
begin
 i:=l; j:=r;
 mid:=v[(l+r) div 2];
 while i<j do
 begin
  while v[i]<mid do inc(i);
  while v[j]>mid do dec(j);
  if i<=j then
  begin
   v[0]:=v[i];
   v[i]:=v[j];
   v[j]:=v[0];
   x[0]:=x[i];
   x[i]:=x[j];
   x[j]:=x[0];
   y[0]:=y[i];
   y[i]:=y[j];
   y[j]:=y[0];
   inc(i); dec(j);
  end;
 end;
 if i<r then qsort(i,r);
 if l<j then qsort(l,j);
end;

function father(x:longint):longint;
var
 i,j:longint;
begin
 if x<>f[x]  then father:=father(f[x])
             else father:=x;
 f[x]:=father;
end;


begin
 max:=maxlongint;
 min:=1;
 readln(n,m);
 for i:=1 to m do
  readln(x[i],y[i],v[i]);
 readln(x1,y1);
 qsort(1,m);
 for i:=1 to n do
  f[i]:=i;
 for i:=1 to m do
 begin
  j:=i-1;
  p:=v[i];
  while (j<=m) and (father(x1)<>father(y1)) do
  begin
   inc(j);
   f[father(x[j])]:=f[father(y[j])];
   q:=v[j];
  end;
  if father(x1)<>father(y1) then break;
  if q/p<max/min then
  begin
   max:=q;
   min:=p;
  end;
  for j:=1 to n do
   f[j]:=j;
 end;
 if max=maxlongint then
 begin
  writeln('IMPOSSIBLE');
  halt;
 end;

 q:=gcd(max,min);
 max:=max div q;
 min:=min div q;
 if min=1 then writeln(max)
          else writeln(max,'/',min) ;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值