道路网(最短路问题)

道路网
(map.pas/c/cpp)
【题目描述】
C国的道路网络由若干条双向线路组成。每条线路途经一些城市(可能会经过多次同一
城市),位于线路上的两个城市a,b通过i号线路互相抵达的费用为 w[i][a] + w[i][b]。现在有若干个询问,询问两城市互相到达的最小费用。
【输入数据】
第一行为城市数n与线路数m。
以下m行每行描述一条线路:
第一个正整数l[i]为i号线路途经的城市数,接下来2*l[i]个正整数,每两个数描述一个城市,依次表示途经的城市j,费用w[i][j];接下来若干行每行两个正整数a,b表示询问a,b之间的最小费用,最后以0 0结束。
【输出数据】
对于每组询问输出一行。
若不存在路径输出 -1,否则输出最小费用。
【样例输入】
4 2
3 1 1 2 1 3 3
3 1 2 2 1 4 2
1 2
3 4
2 4
0 0
【样例输出】
2
7
3
【数据范围】
令T为询问数
10%的数据满足n≤10,m≤3,T≤3。
30%的数据满足n,T≤100,m,l[i]≤15。
50%的数据满足n≤1000,T≤100,m,l[i]≤50。
100%的数据满足n≤100000,m≤300,T,l[i],w[i][j]≤2000。

2 解法
2.1 解法一( 10分)
暴力即可。
2.2 解法二( 30分)
对于线路上每两个城市建边,再跑最短路或floyd。令e = m * l[i] ^2为边数复杂度 或 。
2.3 解法三( 50分)
考虑对线路设点,则对线路中每个城市连一条边权为w[i][j]的边,再跑最短路。令e=m*l[i]复杂度 。
2.4 解法四( 100分)
类似于上面的做法,我们发现线路数特别的少,所以我们仍对线路设点,将两条线路i,j所有交点的w[i][a]+w[j][a]之和取最小值作为i, j的边,然后跑floyd即可,询问时将两点所在线路枚举取最小值即可,复杂度 。

本人蒟蒻一枚=_=,只用spfa写出了五十分的,剩余TLE
有大神路过的话,教教我怎么写T_T
五十分代码如下:

program df;
type point=^node;
node=record
date,ends:longint;
next:point;
end;
var i,j,n,m,x,y,z,k,t:longint;
path:array[0..200000] of point;
a,dis:array[0..200000] of longint;
tm:array[0..5000000] of longint;
b:array[0..200000] of boolean;
procedure com(x,y,z:longint);
var i:point;
begin
i:=path[x];
new(path[x]);
path[x]^.ends:=y;
path[x]^.date:=z;
path[x]^.next:=i;
end;

procedure init;
var i:longint;
begin
for i:=1 to n+m+1 do
begin
dis[i]:=maxlongint div 3;
b[i]:=false;
end;
end;

procedure spfa(x:longint);
var i:point;
h,t,y,u:longint;
begin
init;
h:=0; t:=1; dis[x]:=0; tm[1]:=x; b[x]:=true;
repeat
inc(h);
u:=tm[h];
b[u]:=false;
i:=path[u];
while i<>nil do
begin
y:=i^.ends;
if dis[y]>dis[u]+i^.date then
begin
dis[y]:=dis[u]+i^.date;
if not b[y] then
begin
inc(t);
tm[t]:=y;
b[y]:=true;
end;
end;
i:=i^.next;
end;
until h=t;
end;

begin
assign(input,’map.in’);
reset(input);
assign(output,’map.out’);
rewrite(output);
readln(n,m);
for i:=1 to m do
begin
read(x);
for j:=1 to x do
begin
read(y,z);
com(i+n,y,z); //将每个地铁线当作一个点双向建边(可类比为差分约束中的超级源点,跑最短路即可,还不懂的话,就当地铁是一个点好了,地铁能通到各个点)
com(y,i+n,z);
end;
readln;
end;
dis[0]:=maxlongint div 3;
readln(x,y);
while (x<>0) and (y<>0) do
begin
spfa(x);
if dis[y]<>dis[0] then
writeln(dis[y])
else writeln(-1);
readln(x,y);
end;
close(input);
close(output);
end.

    原文作者:道路修建问题
    原文地址: https://blog.csdn.net/Jackleg/article/details/53141245
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞