1050: [HAOI2006]旅行comf

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1495  Solved: 737
[Submit][Status]

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不可能相同。

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

 题解:这个题嘛,害得我想了好久才发现可以模仿kruskal最小生成树的思想(phile:汗。。。),具体如下——先是将所有的边排个序,然后枚举一个数对(i,j)(i<=j)即当从第i边开始用时,只需要一直用到第j个边既可以使s和t联通(由于边已经排了序,所以这样子能保证对于每个i,j均是最优解),然后这样子跑N次,打擂台取出最小值就可以了——Accept 4860ms(HansBug:是不是太慢了点 *_*)
 
 var
i,j,k,l,m,n,s,t:longint;
mx,my,mm:int64;
a:array[..,..] of longint;
c:array[..] of longint;
function max(x,y:longint):longint;inline;
begin
if x>y then max:=x else max:=y;
end;
function min(x,y:longint):longint;inline;
begin
if x<y then min:=x else min:=y;
end;
function getfat(x:longint):longint;inline;
begin
while x<>c[x] do x:=c[x];
getfat:=x;
end;
procedure startset(x:longint);inline;
var i:longint;
begin
for i:= to x do c[i]:=i;
end;
function tog(x,y:longint):boolean; inline;
begin
exit(getfat(x)=getfat(y));
end;
procedure merge(x,y:longint);inline;
begin
c[getfat(x)]:=getfat(y);
end;
procedure swap(var x,y:longint);inline;
var z:longint;
begin
z:=x;x:=y;y:=z;
end;
procedure sort(l,r:longint);
var i,j,x,y:longint;
begin
i:=l;j:=r;x:=a[(l+r) div ,];
repeat
while a[i,]<x do inc(i);
while a[j,]>x do dec(j);
if i<=j then
begin
swap(a[i,],a[j,]);
swap(a[i,],a[j,]);
swap(a[i,],a[j,]);
inc(i);dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
function gcd(x,y:int64):int64;
var z:int64;
begin
while y<> do
begin
z:=x mod y;
x:=y;
y:=z;
end;
exit(x);
end; begin
readln(n,m);
for i:= to m do readln(a[i,],a[i,],a[i,]);
readln(s,t);
sort(,m);
mx:=;my:=maxlongint;
for i:= to m do
begin
startset(n);
for j:=i to m do
begin
if tog(a[j,],a[j,]) then continue;
merge(a[j,],a[j,]);
if tog(s,t) then
begin
if (my*a[i,])>(mx*a[j,]) then
begin
my:=a[j,];
mx:=a[i,];
end;
break;
end;
end;
end;
if (my=maxlongint) and (mx=) then
begin
writeln('IMPOSSIBLE');
halt;
end;
mm:=gcd(mx,my);
mx:=mx div mm;
my:=my div mm; if mx= then writeln(my) else writeln(my,'/',mx);
end.
05-08 15:12