Description
在有向图
G
G
G 中,每条边的长度均为 1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
- 路径上的所有点的出边所指向的点都直接或间接与终点连通。
- 在满足条件 1 的情况下使路径最短。
注意: 图
G
G
G 中可能存在重边和自环,保证终点没有出边。
请你输出符合条件的路径的长度。
Input Data
第一行有两个用一个空格隔开的整数
n
n
n 和
m
m
m ,表示图有
n
n
n 个点和
m
m
m 条边。
接下来的
m
m
m 行每行 2 个整数
x
、
y
x 、 y
x、y ,之间用一个空格隔开,表示有一条边从点
x
x
x 指向点
y
y
y 。 最后一行有两个用一个空格隔开的整数
s
、
t
s 、 t
s、t ,表示起点为
s
s
s ,终点为
t
t
t 。
Output Data
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出 -1
。
Sample Input 1
3 2
1 2
2 1
1 3
Sample Output 1
-1
Sample Input 2
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
Sample Output 2
3
样例1如上图所示,箭头表示有向道路,圆点表示城市。起点 1 与终点 3 不连通,所以满足题目描述的路径不存在,故输出-1。
样例2如上图所示,满足条件的路径为
1
→
3
→
4
→
5
1 \rightarrow 3 \rightarrow 4 \rightarrow 5
1→3→4→5 。注意点 2 不能在答案路径中,因为点 2 连了一条边到点 6 ,而点 6 不与终 点 5 连通。
对于 30%的数据,
0
<
n
≤
10
,
0
<
m
≤
20
0<n \leq 10,0<m \leq 20
0<n≤10,0<m≤20 ;
对于 60%的数据,
0
<
n
≤
100
,
0
<
m
≤
2000
0<n \leq 100,0<m \leq 2000
0<n≤100,0<m≤2000 ;
对于 100%的数据,
0
<
n
≤
10
,
000
,
0
<
m
≤
200
,
000
,
0
<
x
,
y
,
s
,
t
≤
n
,
x
≠
t
0<n \leq 10,000,0<m \leq 200,000,0<x, y, s, t \leq n, x \neq t
0<n≤10,000,0<m≤200,000,0<x,y,s,t≤n,x=t 。
Tips: 本来以为是从终点开始的拓扑排序。。(只能拿10分呜呜)
其实应该是先通过终点bfs标记谁能到达终点,然后再在标记的限制之上跑Dijkstra算法求最短路。一开始想到了,但是感觉又有点简单就没写。。。以后优先写简单的算法,跑几个特殊样例没问题就交简单的想法,再不行再考虑难的算法。
Code:
struct Node {
int w, x;
bool operator < (const Node& rhs) const {
return w > rhs.w;
}
};
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
int n, m;
cin >> n >> m;
vector<vector<int>> h(n + 1);
vector<vector<Node>> g(n + 1);
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
if (u == v) continue;
g[u].push_back(Node{1, v});
h[v].push_back(u);
}
int s, t;
cin >> s >> t;
queue<int> q;
vector<int> vis(n + 1, 0), tag(n + 1, 0);
q.push(t);
while (!q.empty()) {
int u = q.front();
q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto v : h[u]) {
q.push(v);
}
}
priority_queue<Node> tq;
tq.push(Node{0, s});
vector<int> dis(n + 1, INT_MAX), vit(n + 1, 0);
dis[s] = 0;
while (!tq.empty()) {
int x = tq.top().x;
tq.pop();
if (vit[x]) continue;
vit[x] = 1;
tag[x] = 1;
for (auto p : g[x]) {
int y = p.x;
if (!vis[y]) {
tag[x] = 0;
}
}
if (!tag[x]) continue;
for (auto p : g[x]) {
int y = p.x, z = p.w;
if (dis[y] > dis[x] + z) {
dis[y] = dis[x] + z;
if (!vit[y]) {
tq.push(Node{dis[y], y});
}
}
}
}
cout << (dis[t] == INT_MAX ? -1 : dis[t]) << "\n";
return 0;
}