城市交通
题目
某城市 有N(1<=N<=50)个街区,某些街区由公共汽车线路相连,如在图1中,街区1,2有一条公共汽车线路相连,且由街区1至街区2的时间为34分钟。由于街区与街区之间的距离较近,与等车时间相比可忽略不记,所以这个时间为两趟公共汽车的间隔时间,即平均的等车时间。
由街区1至街区5的最快走法为1-3-5,总时间为44分钟。
现在市政府为了提高城市交通质量,决定加开M(1<=M<=10)条公共汽车线路。若在某两个街区A,B之间加开线路(前提是A、B之间必须已有线路),则从A到B的旅行时间缩小为原来的一半(距离未变,只是等车的时间缩短了一半)。例如,若在1,2之间加开一条线路,则时间变为17分钟,加开两条线路,时间变为8.5分钟,以此类推。所有的线路都是环路,即如果由1至2的时间变为17分钟,则由2至1的时间也变为17分钟。
求加开某些线路,能使由城市1至城市N的时间最少。例如,在图1中,如果M=2,则改变1-3,3-5的线路,总的时间可以减少为22分钟。
输入
输入文件名为City.Inp。
第一行为城市数N与加开线路数M。
第二行至第N+1行,每行为N个实数,第I+1行第J列表示由城市I到城市J的时间。
如果时间为0,则城市I不可能到城市J。
注意:输入数据中,从城市1到城市N至少有一条路线。
输出
输出文件名为City.Out.
第一行为由城市1到城市N的最小时间X(保留小数点后两位)。
第二行至第M+1行为更改的线路。每行由两个整数(x,y)构成。表示将城市x与城市y之间增加一条线路。
样例输入
City.Inp
5 2
0 34 24 0 0
34 0 10 12 0
24 10 0 16 20
0 12 16 0 30
0 0 20 30 0
样例输出
City.Out
22.00
1 3
3 5
=======================
spfa拆点
========================================
type
node=record
m:longint;
x:longint;
end;
var
n,m:longint;
map:array[1..50,1..50]of longint;
dist:array[1..50,0..10]of extended;
f_bo:array[1..50,0..10]of boolean;
g:array[1..50,0..10]of node;
dui:array[1..200000]of node;
procedure init;
begin
assign(input,'city.in');
assign(output,'city.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure print(x,y:longint);
var
i:longint;
begin
if y=m then terminate;
if g[x,y].m=y then
begin
print(g[x,y].x,g[x,y].m)
end
else
begin
for i:=y to g[x,y].m-1 do
writeln(g[x,y].x,' ',x);
print(g[x,y].x,g[x,y].m);
end;
end;
procedure spfa;
var
i,j:longint;
l,r:longint;
now_x,now_m:longint;
t:longint;
begin
//fillchar(dist,sizeof(dist),$7);
for i:=1 to n do
for j:=0 to m do
dist[i,j]:=99999999999;
fillchar(f_bo,sizeof(f_bo),true);
dist[1,m]:=0;
f_bo[1,m]:=false;
l:=0; r:=1;
dui[r].m:=m;
dui[r].x:=1;
repeat
inc(l);
now_x:=dui[l].x;
now_m:=dui[l].m;
for i:=1 to n do
if map[i,now_x]<>0 then
begin
t:=1;
for j:=now_m downto 0 do
begin
if map[now_x,i]/t+dist[now_x,now_m]<dist[i,j] then
begin
dist[i,j]:=map[now_x,i]/t+dist[now_x,now_m];
g[i,j].x:=now_x;
g[i,j].m:=now_m;
if f_bo[i,j] then
begin
f_bo[i,j]:=false;
inc(r);
dui[r].m:=j;
dui[r].x:=i;
end;
end;
t:=t shl 1;
end;
end;
f_bo[now_x,now_m]:=true;
until l>=r;
writeln(dist[n,0]:0:2);
print(n,0);
end;
procedure main;
var
i,j:longint;
begin
readln(n,m);
for i:=1 to n do
for j:=1 to n do
read(map[i,j]);
spfa;
end;
begin
init;
main;
terminate;
end.