最优乘车
时间限制: 1 Sec 内存限制: 128 MB
题目描述
H城是一个旅游胜地,为方便游客,在各个旅游景点及宾馆、饭店等地设置了N个巴士站,并开通了M条一些单向巴士线路。
现在用整数1,2,…,n给H城的所有巴士站编号,约定CUP饭店的巴士站编号为1,S公园巴士站的编号为N。
写一个程序,寻找一个从CUP饭店到S公园的过程中换车的次数最少的乘车方案。
输入
输入第一行有两个数字M和N(1<=M<=100 1
输出
输出只有一行。如果无法乘巴士从饭店到达S公园,则输出
“N0”,否则输出你的程序所找到的最少换车次数,换车次数为0表示不需换车即可到达·
样例输入
3 7
6 7
4 7 3 6
2 1 3 5
样例输出
2
题解
对于每个点,如果有不同线路的相同点,那么我们拓展这个点的节点,并与原节点为无向边权为1相连
例如 1 3 5和 3 7
1–>3–>5
我们拓展3的同源节点4,并且3<–>4,边权为1,4–>7
const maxn=maxlongint;
var
s,dist,f:array[0..6100]of longint;
t:array[0..5000,0..5000]of longint;
w:array[0..5010,0..5010]of longint;
i,j,k:longint;
n,m,a,b,start,finish,sum,v,min:longint;
procedure prepare;
begin
readln(m,n); k:=n+1;
for i:=1 to (n+m)*2 do
for j:=1 to (n+m)*2 do
w[i,j]:=maxn; sum:=n;
end;
begin
prepare;
for i:=1 to m do
begin
read(a);
if f[a]=0
then begin f[a]:=1; t[a,0]:=1; t[a,1]:=a; end
else begin
inc(t[a,0]); t[a,t[a,0]]:=k; inc(k);
for j:=1 to t[a,0]-1 do
begin w[k-1,t[a,j]]:=1; w[t[a,j],k-1]:=1; end;
a:=k-1;
end;
while not eoln do
begin
read(b);
if f[b]=0
then
begin
f[b]:=1;
t[b,0]:=1; t[b,1]:=b;
w[a,b]:=0;
a:=b;
end
else
begin
inc(sum);
inc(t[b,0]); t[b,t[b,0]]:=k;
w[a,k]:=0;
for j:=1 to t[b,0]-1 do
begin w[k,t[b,j]]:=1; w[t[b,j],k]:=1; end;
a:=k;
inc(k);
end;
end;
readln;
end;
start:=k+1; finish:=k+2;
//writeln(start,' ',finish);
for i:=1 to t[1,0] do
begin w[start,t[1,i]]:=0; w[t[1,i],start]:=0; end;
for i:=1 to t[n,0] do
begin w[finish,t[n,i]]:=0; w[t[n,i],finish]:=0; end;
{for i:=1 to k+2 do
for j:=1 to k+2 do
if w[i,j]<>maxn
then writeln(i,'->',j,' ',w[i,j]);}
for i:=1 to finish do
dist[i]:=maxn;
dist[start]:=0;
while s[0]<>k+2 do
begin
min:=maxlongint;
for i:=1 to k+2 do
if (dist[i]<min)and(s[i]=0)
then begin min:=dist[i]; v:=i; end;
for i:=1 to k+2 do
if (s[i]=0)and(w[v,i]<>maxn)and(dist[v]+w[v,i]<dist[i])
then dist[i]:=dist[v]+w[v,i];
s[v]:=1; inc(s[0]);
if s[finish]=1 then break;
end;
if dist[finish]=maxn
then writeln('NO')
else writeln(dist[finish]);
end.