[NOI1997]最优乘车

最优乘车

时间限制: 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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值