【问题描述】

给出了一张有N个点M条边的加权有向无环图,接下来有Q个询问,每个询问包括2个结点X和Y,要求算出从X到Y的一条路径,使得密度最小(密度的定义为,路径上边的权值和除以边的数量)

注意:题目描述有误,实际上是有环的

【文件输入】

第一行包括2个整数N和M。
第2到第M+1行,每行三个数字A、B、W,表示从A到B有一条权值为W的有向边。
第M+2行只有一个整数Q。
接下来的Q行,每行有两个整数X和Y,表示一个询问。
【文件输出】
对于每个询问输出一行,表示该询问的最小密度路径的密度(保留3位小数),如果不存在从X到Y的一条路径,则输出“OMG!”
【样例输入】
3 3
1 3 5
2 1 6
2 3 6
2
1 3
2 3
【样例输出】
5.000
5.500
【数据范围】
对于60%的数据,有1≤N≤10;1≤M≤100,1≤W≤1000,1≤Q≤1000;
对于100%的数据,有1≤N≤50;1≤M≤1000,1≤W≤100000,1≤Q≤100000。

Solutions

1.看数据范围,由于N很小,所以要向floyd方向考虑,只需要在记录最短路的f[i,j]中再添加一维l,表示到该点的路径条数

path1.pas

2.也可以通过二维的spfa解决,dis[i,j]代表源点到点i,经过j条边的最短路

path2.pas
program fourth;
type
node = record
dian,num : Longint;
end;
var
n,m,i,j,k,x,y,p : longint;
map : array[1..100,1..100] of longint;
dis : array[1..100,0..1000] of longint;
v : array[1..100,0..1000] of boolean;
f : array[1..1000] of boolean;
q : array[1..100000] of node;
ans : array[1..100,1..1000] of double;
procedure init;
var
x,y,z : longint;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y,z);
if (map[x,y]=0) or (map[x,y]>z) then
map[x,y]:=z;
end;
end; { init }
procedure spfa(x : longint);
var
min : double;
head,tail,j : longint;
temp,num,i : longint;
begin
fillchar(v,sizeof(v),false);
filldword(dis,sizeof(dis)>>2,1000000);
tail:=1; head:=1;
q[1].dian:=x;
q[1].num:=0;//存储边数
v[x,0]:=true;
dis[x,0]:=0;
while head<=tail do
begin
temp:=q[head].dian;
num:=q[head].num;
for i:=1 to n do
if map[temp,i]<>0 then
if num+1<=n then
begin
if dis[i,num+1]>dis[temp,num]+map[temp,i] then
dis[i,num+1]:=dis[temp,num]+map[temp,i];
if not v[i,num+1] then
begin
inc(tail);
q[tail].dian:=i;
q[tail].num:=num+1;
v[i,num+1]:=true;
end;
end;
inc(head);
v[temp,num]:=false;
end;
for i:=1 to n do
if i<>x then
begin
min:=maxlongint;
for j:=1 to n do
if (dis[i,j]<>1000000) and (dis[i,j]/j<min) then
min:=dis[i,j]/j;
if min<>maxlongint then ans[x,i]:=min
else
ans[x,i]:=-1;
end;
end; { spfa }
begin
assign(input,'path.in'); reset(input);
//assign(output,'path.out'); rewrite(output);
init;
readln(p);
for i:=1 to p do
begin
readln(x,y);
if not f[x] then
spfa(x);
f[x]:=true;
if ans[x,y]<>-1 then
writeln(ans[x,y]:0:3)
else
writeln('OMG!');
end;
close(input);
close(output);
end.

两种方法中边数都控制在n以内,是因为数据原因,由于数据有环,所以就会出现边数越多,答案越小的情况

posted on 2012-03-11 16:53  淡·雅·墨  阅读(430)  评论(0编辑  收藏  举报