在有向圖 G 中,每條邊的長度均爲 1,現給定起點和終點,請你在圖中找一條從起點到 終點的路徑,該路徑滿足以下條件:
- 路徑上的所有點的出邊所指向的點都直接或間接與終點連通。
- 在滿足條件 1 的情況下使路徑最短。
注意:圖 G 中可能存在重邊和自環,題目保證終點沒有出邊。 請你輸出符合條件的路徑的長度。
【樣例輸入1】
3 2
1 2
2 1
1 3
【樣例輸出1】
-1
【樣例輸入2】
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
【樣例輸出2】
3
【解題思路】
又是要用鄰接表的題,我又華麗麗地用了鄰接矩陣,加上當初SB一般的用廣搜+深搜去搜能到的頂點,用了兩個布爾型數組,求最短路的時候用了floyed(其實這個都沒什麼了,之前的就足夠MLE了……),再次爆零……
OK,吐槽完之後,繼續來說正解。
鄰接表,不多說了,以後看到需要存儲邊的題目都去用鄰接表!管你有沒有權。由於這題需要判斷能否到達終點,於是我們需要反向存儲。一遍DFS找到所有不能直接或間接到達的點,將它們的所有的入邊的點全部刪掉,如果起點無法到達的話,就輸出-1,否則就是求最短路了。
【代碼實現】
1 type rec=record 2 c,next:longint; 3 end; 4 var e:array[1..200000] of rec; 5 g:array[1..10000] of longint; 6 efree,i,n,m,k,x,y,s,t,j:longint; 7 a:array[1..10000] of longint; 8 f,flag:array[1..10000] of boolean; 9 procedure add; 10 begin 11 e[efree].c:=x; 12 e[efree].next:=g[y]; 13 g[y]:=efree; 14 inc(efree); 15 end; 16 procedure dfs(x:longint); 17 var j:longint; 18 begin 19 f[x]:=true; 20 j:=g[x]; 21 while j<>0 do 22 begin 23 if not f[e[j].c] then 24 dfs(e[j].c); 25 j:=e[j].next; 26 end; 27 end; 28 procedure dijkstra; 29 var i,j,min,pos:longint; 30 begin 31 fillchar(f,sizeof(f),false); 32 f[t]:=true; 33 a[t]:=0; 34 for j:=1 to n do 35 begin 36 pos:=t; 37 min:=maxint; 38 for i:=1 to n do 39 if (not f[i])and(a[i]<min)and(flag[i]) then 40 begin 41 pos:=i; 42 min:=a[i]; 43 end; 44 f[pos]:=true; 45 i:=g[pos]; 46 while i<>0 do 47 begin 48 if flag[e[i].c] then 49 if a[e[i].c]>a[pos]+1 then 50 a[e[i].c]:=a[pos]+1; 51 i:=e[i].next; 52 end; 53 end; 54 end; 55 begin 56 readln(n,m); 57 efree:=1; 58 for i:=1 to m do 59 begin 60 readln(x,y); 61 add; 62 end; 63 readln(s,t); 64 dfs(t); 65 flag:=f; 66 for i:=1 to n do 67 if not f[i] then 68 begin 69 j:=g[i]; 70 while j<>0 do 71 begin 72 flag[e[j].c]:=false; 73 j:=e[j].next; 74 end; 75 end; 76 if not flag[s] then 77 begin 78 writeln(-1); 79 halt; 80 end; 81 for i:=1 to n do 82 a[i]:=maxint; 83 dijkstra; 84 writeln(a[s]); 85 end.