在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到 终点的路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件 1 的情况下使路径最短。
注意:图 G 中可能存在重边和自环,题目保证终点没有出边。 请你输出符合条件的路径的长度。
第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。
接下来的 m 行每行 2 个整数 x、y,之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s、t,表示起点为 s,终点为 t。
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。
如果这样的路径不存在,输出-1。
3 2
1 2
2 1
1 3
-1
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
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
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.