1050: [HAOI2006]旅行comf
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1456 Solved: 715
[ 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
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
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
HINT
【数据范围】
1< N < = 500
1 < = x, y < = N,0 < v < 30000,x ≠ y
0 < M < =5000
Source
喜闻乐见刷水。。
我也不知道算不算水题,反正一眼题。。。
很明显嘛。。
枚举最短边,二分最长边,每次用DFS判定
复杂度O(nmlogm)
最开始的时候过不去。。被卡常数
然后加了一点小剪枝,就是每次只判定比当前优的。。
然后最开始被卡精度真是爽。。
Code:
const maxn=501;
maxm=10001;
var headlist:array[0..maxn] of longint;
vis:array[0..maxn] of boolean;
next,t,w,a:array[0..maxm] of longint;
map:array[0..maxn,0..maxn] of boolean;
pppp,time,tmp,left,right,data,re1,re2,now1,mid,l,r,num,j,k,n,m,x,y,z:int64;
i:longint;
function gcd(a,b:longint):longint;
begin
if b=0 then exit(a);
exit(gcd(b,a mod b));
end;
procedure init;
begin
readln(n,m);
for i:=1 to n do headlist[i]:=-1;
for i:=1 to m do
begin
readln(x,y,z);
map[x,y]:=true;
map[y,x]:=true;
inc(num);
a[i]:=z;
next[num]:=headlist[x];
headlist[x]:=num;
t[num]:=y;
w[num]:=z;
inc(num);
next[num]:=headlist[y];
headlist[y]:=num;
t[num]:=x;
w[num]:=z;
end;
readln(x,y);
end;
procedure qsort(left,right:longint);
var i,j,mid:longint;
begin
i:=left; j:=right; mid:=a[(i+j) shr 1];
repeat
while a[i]<mid do inc(i);
while a[j]>mid do dec(j);
if i<=j then begin
tmp:=a[i]; a[i]:=a[j]; a[j]:=tmp;
inc(i); dec(j);
end;
until i>j;
if j>left then qsort(left,j);
if i<right then qsort(i,right);
end;
procedure search(u:longint);
var i:longint;
begin
vis[u]:=true;
i:=headlist[u];
while i<>-1 do
begin
if (w[i]<=mid) and (w[i]>=now1) and (not vis[t[i]]) then search(t[i]);
i:=next[i];
end;
end;
procedure main;
begin
init;
if map[x,y] then begin
writeln(1);
halt;
end;
fillchar(vis,sizeof(vis),false);
now1:=0; mid:=maxlongint;
search(x);
if not(vis[y]) then begin
writeln('IMPOSSIBLE');
halt;
end;
qsort(1,m); re1:=50000; re2:=1;
for i:=1 to m-1 do
begin
now1:=a[i];
left:=i+1; right:=m;
repeat
fillchar(vis,sizeof(vis),false);
mid:=a[trunc((left+right) shr 1)];
if mid*re2>now1*re1 then begin
right:=trunc((left+right) shr 1)-1;
continue;
end;
search(x);
if vis[y] then begin
if mid*re2<now1*re1 then begin
re1:=mid; re2:=now1;
end;
right:=trunc((left+right) shr 1)-1;
end
else left:=trunc((left+right) shr 1)+1;
until left>right;
end;
data:=gcd(re1,re2);
re1:=re1 div data;
re2:=re2 div data;
if re2<>1 then writeln(re1,'/',re2)
else writeln(re1);
end;
begin
main;
end.