#AtCoder Beginner Contest 218——F-Blocked Roads

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值