題解 P2296 【尋找道路】

在有向圖 G G 中,每條邊的長度均爲 1 1 ,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑知足如下條件:html

  1. 路徑上的全部點的出邊所指向的點都直接或間接與終點連通。
  2. 在知足條件 1 1 的狀況下使路徑最短。

注意:圖 GG 中可能存在重邊和自環,題目保證終點沒有出邊。node

請你輸出符合條件的路徑的長度。c++

這道題,咱們考慮哪些點可以到達終點,問題等價於:反向建邊後,終點能到達哪些點。git

void dfs(int x){
	h[x]=true;
	for(auto i:E[x])
		if(!h[i])dfs(i);
}

E E 正是反向建邊後的邊集。web

h x = 1 h_x=1 就表示 x x 號點能到終點。app

因此,咱們能夠判斷哪些點能夠走了。svg

能通過的點要知足 2 2 個條件:spa

  1. 它本身能到達終點
  2. 它的出邊所指向的點都能達到終點
for(int i=1;i<=n;i++)
	if(h[i]){
		dis[i]=true;
		for(auto j:v[i])
			if(!h[j]){dis[i]=false;break;}
	}

這部作完了,就能夠開始 b f s bfs 了。code

邊權全都是 1 1 天然是第 1 1 次搜到的就是最優解。xml

q.push((node){s,0});
while(q.size()){
	node x=q.front();
	if(x.x==t){
		cout<<x.s;
		return 0;
	}
	for(auto i:v[x.x])
		if(dis[i]&&!vis[i]){
			vis[i]=true;
			q.push((node){i,x.s+1});
		}
	q.pop();
}cout<<-1;

仍是很簡單的。

總代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF){
	T RR=1;FF=0;char CH=getchar();
	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
	FF*=RR;
}
struct node{
	int x,s;
};
bool h[10010],vis[10010];
int n,m,dis[10010],s,t;
vector<int>v[10010];
vector<int>E[10010];
queue<node>q;
void dfs(int x){
	h[x]=true;
	for(auto i:E[x])
		if(!h[i])dfs(i);
}
int main(){
	read(n);read(m);
	for(int i=1;i<=m;i++){
		int x,y;read(x);read(y);
		v[x].push_back(y);
		E[y].push_back(x);
	}
	read(s);read(t);
	dfs(t);
	for(int i=1;i<=n;i++)
		if(h[i]){
			dis[i]=true;
			for(auto j:v[i])
				if(!h[j]){dis[i]=false;break;}
		}
	q.push((node){s,0});
	while(q.size()){
		node x=q.front();
		if(x.x==t){
			cout<<x.s;
			return 0;
		}
		for(auto i:v[x.x])
			if(dis[i]&&!vis[i]){
				vis[i]=true;
				q.push((node){i,x.s+1});
			}
		q.pop();
	}cout<<-1;
	return 0;
}