描述 Description
在有向圖 G 中,每條邊的長度均爲 1,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑滿足以下條件:
1.路徑上的所有點的出邊所指向的點都直接或間接與終點連通。
2.在滿足條件 1 的情況下使路徑最短。
注意:圖 G 中可能存在重邊和自環,題目保證終點沒有出邊。
請你輸出符合條件的路徑的長度。
輸入輸出格式
第一行有兩個用一個空格隔開的整數 n 和 m,表示圖有 n 個點和 m 條邊。
接下來的 m 行每行 2 個整數 x、y,之間用一個空格隔開,表示有一條邊從點 x 指向點y。
最後一行有兩個用一個空格隔開的整數 s、t,表示起點爲 s,終點爲 t。
輸出只有一行,包含一個整數,表示滿足題目描述的最短路徑的長度。如果這樣的路徑不存在,輸出-1。
樣例輸入 Sample Input
輸入樣例1
3 2
1 2
2 1
1 3
輸入樣例2
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
輸出樣例1
-1
輸出樣例2
3
時間限制
1s
註釋 Hint
輸入輸出樣例1說明
如上圖所示,箭頭表示有向道路,圓點表示城市。起點 1 與終點 3 不連通,所以滿足題目描述的路徑不存在,故輸出-1。
輸入輸出樣例2說明
如上圖所示,滿足條件的路徑爲 1->3->4->5。注意點 2 不能在答案路徑中,因爲點 2連了一條邊到點 6,而點 6 不與終點 5 連通。
數據說明
對於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,s≠t,x≠t。
這道題的思路比較好想一些,我們可以建雙向邊,對於正邊和反邊我們標記一下即可。
那麼建完邊後我們先從終點bfs一遍,只跑反向邊,對於每個遍歷到的邊進行標記,這樣我們就可以找出不能直接或間接到達終點的點。
得到這些點後,我們再遍歷這些點的反向邊的出邊,將與這些點相連的點進行標記。
標記完後我們剩下的沒有被第二次標記的點就是可以走的點。這時我們再從起點bfs一遍,只跑正向邊,且不走被第二次標記過的點,那麼第一次到達終點的時候就是可到達的最短路。
#include<bits/stdc++.h>
#define ll long long
#define MAXN 500010
#define N 201
#define INF 0x7f7f7f7f
#define gtc() getchar()
using namespace std;
template <class T>
inline void read(T &s){
s = 0; T w = 1, ch = gtc();
while(!isdigit(ch)){if(ch == '-') w = -1; ch = gtc();}
while(isdigit(ch)){s = s * 10 + ch - '0'; ch = gtc();}
s *= w;
}
template <class T>
inline void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x/10);
putchar(x % 10 + '0');
}
struct node{
int y, ne, z;
}e[MAXN];
int lin[MAXN], len = 0;
inline void add(int x, int y, int z){
e[++len].y = y, e[len].ne = lin[x], lin[x] = len;
e[len].z = z;
}
int n, m;
int st, ed;
int col[MAXN], vis[MAXN];
void bfs(int u){
queue<int> q;
q.push(u);
vis[u] = 1;
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = lin[x]; i; i = e[i].ne){
int y = e[i].y;
if(e[i].z == 1) continue;
if(vis[y]) continue;
vis[y] = 1;
q.push(y);
}
}
}
void bfs2(int u){//這個不是bfs,之前寫錯寫成bfs,後來直接在這個函數裏改了。
col[u] = 1;
for(int i = lin[u]; i; i = e[i].ne){
int y = e[i].y;
if(e[i].z == 1) continue;
if(col[y]) continue;
col[y] = 1;
q.push(y);
}
}
int dis[MAXN];
void bfs3(int u){
memset(dis, INF, sizeof(dis));
dis[u] = 0;
queue<int> q;
q.push(u);
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = lin[x]; i; i = e[i].ne){
int y = e[i].y;
if(e[i].z == 2) continue;
if(col[y]) continue;
if(dis[y] != INF) continue;
dis[y] = dis[x] + 1;
q.push(y);
}
}
}
int main()
{
read(n), read(m);
int x, y;
for(int i = 1; i <= m; ++i){
read(x), read(y);
add(x, y, 1); add(y, x, 2);//1爲正邊,2爲負邊
}
read(st), read(ed);
bfs(ed);
for(int i = 1; i <= n; ++i){
if(!vis[i]){
bfs2(i);
}
}
bfs3(st);
if(dis[ed] == INF) puts("-1");
else printf("%d\n", dis[ed]);
return 0;
}