[NOIP2014]寻找道路

寻找道路

描述

在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到 终点的路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件 1 的情况下使路径最短。
注意:图 G 中可能存在重边和自环,题目保证终点没有出边。 请你输出符合条件的路径的长度。

输入格式

第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。
接下来的 m 行每行 2 个整数 x、y,之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s、t,表示起点为 s,终点为 t。

输出格式

输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。
如果这样的路径不存在,输出-1。

样例1

样例输入1

3 2
1 2
2 1
1 3

样例输出1

-1

样例2

样例输入2

6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5

样例输出2

3

限制

对于 30%的数据,0 < n ≤ 10,0 < m ≤ 20;
对于 60%的数据,0 < n ≤ 100,0 < m ≤ 2000;
对于 100%的数据,0 < n ≤ 10,000,0 < m ≤ 200,000,0 < x,y,s,t ≤ n,x ≠ t。

提示

【输入输出样例1说明】

如上图所示,箭头表示有向道路,圆点表示城市。起点 1 与终点 3 不连通,所以满足题目描述的路径不存在,故输出-1。
【输入输出样例2说明】

如上图所示,满足条件的路径为 1->3->4->5。注意点 2 不能在答案路径中,因为点 2 连了一条边到点 6,而点 6 不与终点 5 连通。

来源

NOIP2014 提高组 Day2

题解

  • 反向建图,然后BFS出其他点终点是否能到达
  • 对于不能到达的点,与其相连的点也不能到达,再把它们去掉
  • BFS原图中起点到终点的距离
var
 z,w:array[0..220000,1..2]of longint;
 c,y,x:array[0..10000]of longint;
 v:array[0..30000]of longint;
 i,j,k:longint;
 n,m:longint;
 a,b,len,s,t,head,tail,u,tt,ans:longint;
procedure initw(a,b:longint);
begin
 w[len,1]:=b;
 if w[a,2]=0
 then w[a,2]:=len else w[w[a,1],2]:=len;
 w[a,1]:=len;
end;

procedure initz(a,b:longint);
begin
 z[len,1]:=b;
 if z[a,2]=0
 then z[a,2]:=len else z[z[a,1],2]:=len;
 z[a,1]:=len; inc(len);
end;

procedure prepare;
begin
 readln(n,m); len:=n+1;
 for i:=1 to m do
  begin
   readln(a,b);
   initw(a,b);
   initz(b,a);
  end;
 readln(s,t);
end;

begin
 prepare;
 v[1]:=t; head:=1; tail:=2;
 while head<tail do
  begin
   u:=v[head]; tt:=z[u,2];
   while tt<>0 do
    begin
     if x[z[tt,1]]<>1
     then begin x[z[tt,1]]:=1; v[tail]:=z[tt,1]; inc(tail); end;
     tt:=z[tt,2];
    end;
   inc(head);
  end;
 x[t]:=1;
 for i:=1 to n do
  c[i]:=x[i];
 for i:=1 to n do
  begin
   if x[i]=1 then continue;
   tt:=z[i,2];
   while tt<>0 do
    begin
     c[z[tt,1]]:=0;
     tt:=z[tt,2];
    end;
  end;
 head:=1; tail:=2; v[1]:=s; ans:=0;
 while head<tail do
  begin
   a:=head; b:=tail; inc(ans);
   for i:=a to b-1 do
    begin
     u:=v[head]; tt:=w[u,2];
     while tt<>0 do
      begin
       if (y[w[tt,1]]=0)and(c[w[tt,1]]=1)
       then begin y[w[tt,1]]:=1; if w[tt,1]=t then begin writeln(ans); halt; end; v[tail]:=w[tt,1]; inc(tail); end;
       tt:=w[tt,2];
      end;
     inc(head);
    end;
  end;
 writeln(-1);
end.

你可能感兴趣的:([NOIP2014]寻找道路)