题目描述
难度分:1753
输入n(2≤n≤400),m(1≤m≤n×(n−1)),表示一个n点m边的有向图。保证图中无自环和重边。
然后输入m条边,每条边输入x y
,表示一条x到y的有向边,边权为1。节点编号从1开始。
输出m个数,其中第i个数表示删除输入的第i条边后,从1到n的最短路长度。如果无法从1到达n,输出−1。
输入样例1
3 3
1 2
1 3
2 3
输出样例1
1
2
1
输入样例2
4 4
1 2
2 3
2 4
3 4
输出样例2
-1
2
3
2
输入样例3
5 10
1 2
1 4
1 5
2 1
2 3
3 1
3 2
3 5
4 2
4 3
输出样例3
1
1
3
1
1
1
1
1
1
1
输入样例4
4 1
1 2
输出样例4
-1
算法
BFS
+分情况讨论
本题是无权图,所以求最短路用BFS
就可以了。我们先从1开始进行BFS
,求出1到所有其他节点的最短路,在求的过程中将前驱节点保留在from数组中,也就是说from[u]=v表示在最短路上u的前面是v。然后从n节点开始,利用from数组追到起点1,这样就能得到一条最短路path,将这条最短路上的边id都存入到一个哈希集合path中。
遍历i∈[1,m],判断每条边的答案:
- 如果i不在path上,那说明最短路不受i这条边的影响,删边之前1到n的距离是多少就是多少。
- 如果i在path上,就重新跑一遍
BFS
,在这个过程中忽略i这条边得到一个最短路。
复杂度分析
时间复杂度
这个算法乍一看感觉会超时,但实际上非常巧妙。由于1到n的最短路最长也就是n−1,所以重新进行BFS
的次数最多也就是O(n)级别,而每次BFS
求最短路时间复杂度为O(n+m)。大部分情况下O(1)就能得到答案。因此,整个算法的时间复杂度为O(n(n+m)+m)。
空间复杂度
图的邻接表空间占用是O(n+m)。from数组、dist数组空间占用为O(n)。还需要一个edge2id数组,是个O(n2)的数组,edge2id[u][v]表示边uv的编号。因此,整个算法的额外空间复杂度为O(n2+n+m)。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 401, INF = 0x3f3f3f3f;
vector<int> graph[N];
int n, m, from[N], dist[N], edge2id[N][N];
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
graph[i].clear();
dist[i] = INF;
}
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
graph[u].push_back(v);
edge2id[u][v] = i;
}
queue<int> q;
q.push(1);
dist[1] = 0;
while(!q.empty()) {
int cur = q.front();
q.pop();
for(int nxt: graph[cur]) {
if(dist[nxt] > dist[cur] + 1) {
dist[nxt] = dist[cur] + 1;
q.push(nxt);
from[nxt] = cur;
}
}
}
unordered_set<int> path;
int cur = n;
while(1) {
int pre = from[cur];
if(pre == 0) break;
int index = edge2id[pre][cur];
cur = pre;
path.insert(index);
if(cur == 1) break;
}
int ans = dist[n];
for(int i = 1; i <= m; i++) {
if(path.count(i)) {
for(int j = 1; j <= n; j++) {
dist[j] = INF;
}
q.push(1);
dist[1] = 0;
while(!q.empty()) {
int cur = q.front();
q.pop();
for(int nxt: graph[cur]) {
if(edge2id[cur][nxt] == i) continue;
if(dist[nxt] > dist[cur] + 1) {
dist[nxt] = dist[cur] + 1;
q.push(nxt);
}
}
}
printf("%d\n", dist[n] == INF? -1: dist[n]);
}else {
printf("%d\n", ans == INF? -1: ans);
}
}
return 0;
}