题目地址:
https://www.acwing.com/problem/content/description/516/
在有向图
G
G
G中,每条边的长度均为
1
1
1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1.路径上的所有点的出边所指向的点都直接或间接与终点连通。
2.在满足条件
1
1
1的情况下使路径最短。
注意:图
G
G
G中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入格式:
第一行有两个用一个空格隔开的整数
n
n
n和
m
m
m,表示图有
n
n
n个点和
m
m
m条边。
接下来的
m
m
m行每行
2
2
2个整数
x
x
x、
y
y
y,之间用一个空格隔开,表示有一条边从点
x
x
x指向点
y
y
y。
最后一行有两个用一个空格隔开的整数
s
s
s、
t
t
t,表示起点为
s
s
s,终点为
t
t
t。
输出格式:
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。
如果这样的路径不存在,输出
−
1
−1
−1。
数据范围:
0
<
n
≤
10000
0<n≤10000
0<n≤10000
0
<
m
≤
200000
0<m≤200000
0<m≤200000
0
<
x
,
y
,
s
,
t
≤
n
,
s
≠
t
0<x,y,s,t≤n,s≠t
0<x,y,s,t≤n,s=t
建立原图和反向图,先在反向图里从终点开始进行DFS,标记一下终点能走到的点,设 x x x为不能走到的点,那么首先, x x x自己肯定是不合法的(因为 x x x在原图里无法走到终点),接着,如果某个点能走到 x x x,那么这个点也不合法(因为它走到了一个与终点不连通的点)。将所有不合法的点进行标记,然后在原图中BFS求一下最短路即可,略过不合法的点。代码如下:
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int N = 1e4 + 10, M = 2e5 + 10;
int n, m;
int st, en;
int h1[N], e1[M], ne1[M], idx1;
int h2[N], e2[M], ne2[M], idx2;
bool vis[N], cannot_use[N];
#define add(a, b) \
e1[idx1] = b, ne1[idx1] = h1[a], h1[a] = idx1++, e2[idx2] = a, \
ne2[idx2] = h2[b], h2[b] = idx2++
void dfs(int u) {
vis[u] = true;
for (int i = h2[u]; ~i; i = ne2[i])
if (!vis[e2[i]]) dfs(e2[i]);
}
int bfs() {
if (cannot_use[st]) return -1;
memset(vis, 0, sizeof vis);
queue<int> q;
q.push(st);
vis[st] = true;
int res = 0;
while (q.size()) {
res++;
for (int i = q.size(); i; i--) {
auto t = q.front();
q.pop();
for (int j = h1[t]; ~j; j = ne1[j]) {
int ne = e1[j];
if (vis[ne] || cannot_use[ne]) continue;
if (ne == en) return res;
vis[ne] = true;
q.push(ne);
}
}
}
return -1;
}
int main() {
memset(h1, -1, sizeof h1);
memset(h2, -1, sizeof h2);
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
}
scanf("%d%d", &st, &en);
dfs(en);
for (int i = 1; i <= n; i++) {
if (!vis[i]) cannot_use[i] = true;
for (int j = h1[i]; ~j; j = ne1[j]) {
int v = e1[j];
if (!vis[v]) {
cannot_use[i] = true;
break;
}
}
}
printf("%d\n", bfs());
}
时空复杂度 O ( n + m ) O(n+m) O(n+m)。