[noip2014]尋找道路

描述 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章