AtCoder Beginner Contest 218——F-Blocked Roads
题意:给一个无向图,问对于每一条边,将其去除后的最短路是多少
思路:我们先求一条最短路,这条最短路的边一定不会到400条,我们将在最短路里的边存下来(虽然最短路有多条,这里我们存一条即可),然后遍历每条边,如果该边在最短路里,那么把它去除跑dijstra,如果他不在最短路里,那么直接输出第一次跑的 dis[n] 即可,复杂度不会超过n*nlogm
注意:存最短路时存的时边的编号,数组别开小,我是沙比(=-=)~
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define douinf 0x3f3f3f3f
#define IO ios::sync_with_stdio(false)
#define bug cout << "-----\n"
#define eps 1e-10
typedef long long ll;
const int N = 500;
const int M = 200000;
int e[M],ne[M],w[M],h[N],idx;
int n,m;
int dis[N],vis[N],ok[M],pre[N],mp[N][N];
struct vge{
int to,len;
bool operator < (const vge a)const {
return len > a.len;
}
};
priority_queue<vge> q;
void add(int x,int y,int z) {
mp[x][y] = idx;
e[idx] = y;w[idx] = z;ne[idx] = h[x];h[x] = idx ++;
}
int dij(int p) {
while(!q.empty())q.pop();
memset(vis , 0 , sizeof vis);
memset(dis , 0x3f , sizeof dis);
dis[1] = 0;q.push({1 , 0});
while(!q.empty()) {
vge g = q.top();q.pop();
if(vis[g.to])continue;
vis[g.to] = 1;
for(int i = h[g.to] ; ~i ; i = ne[i]) {
int x = e[i];
if(dis[x] > dis[g.to] + w[i]) {
dis[x] = dis[g.to] + w[i];
q.push({x , dis[x]});
if(!p)pre[x] = g.to;
}
}
}
if(p)return dis[n];
int x = n;
while(pre[x] != -1) {
ok[mp[pre[x]][x]] = 1;
x = pre[x];
}
return dis[n];
}
int main() {
IO;memset(h , -1 , sizeof h);
memset(pre , -1 , sizeof pre);
cin >> n >> m;
for(int i = 0 ; i < m ; i ++){
int x,y;cin >> x >> y;
add(x , y , 1);
}
int ans = dij(0);
if(ans == inf) {
for(int i = 0 ; i < m ; i ++)
cout << -1 << '\n';
return 0;
}
for(int i = 0 ; i < m ; i ++) {
if(ok[i]) {
int temp = w[i];
w[i] = inf;
int res = dij(1);
if(res == inf)cout << -1 << '\n';
else cout << res << '\n';
w[i] = temp;
}
else {
cout << ans << '\n';
}
}
return 0;
}