Loading

AtCoder-abc257_f Teleporter Setting

Teleporter Setting

bfs

先构建一个 0 号虚拟点,最后再遍历这个点是其他的点

答案有两种来源:

  1. 本身从 1 直接到达 n(可经过 0 号虚拟点)

  2. 经过 0 号虚拟点和当前假设的点 i 之间的代价为 0 的特殊边

对于第一种情况,只用计算最短路即可

对于第二种情况,则为 min(dis[1][0] + dis[i][n], dis[1][i] + dis[0][n])

综上,计算出 1 和 n 到其他所有点的最短路即可,然后枚举假设 0 号虚拟点为 i 号点,然后找最小的情况

我原本的写法比较笨,现在改用了上述这种写法

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <array>
#include <algorithm>
using namespace std;
const int maxn = 3e5 + 10;
const int inf = 1e8 + 10;
int n, m;
vector<int>gra[maxn];

vector<int> bfs(int s)
{
    queue<array<int, 2> >q;
    vector<int> dis(n + 1, inf);
    q.push({s, 0});
    while(q.size())
    {
        auto [x, d] = q.front();
        q.pop();
        if(dis[x] != inf) continue;
        dis[x] = d;
        for(auto i : gra[x])
            if(dis[i] == inf) q.push({i, d + 1});
    }
    return dis;
}

int main()
{
    cin >> n >> m;
    for(int i=0; i<m; i++)
    {
        int x, y;
        cin >> x >> y;
        gra[x].push_back(y);
        gra[y].push_back(x);
    }
    auto dis1 = bfs(1);
    auto disn = bfs(n);
    for(int i=1; i<=n; i++)
    {
        int ans = min({dis1[n], dis1[0] + disn[i], dis1[i] + disn[0]});
        if(ans == inf) ans = -1;
        if(i != 1) cout << " ";
        cout << ans;
    }
    cout << endl;
    return 0;
}
posted @ 2022-07-02 15:32  dgsvygd  阅读(75)  评论(0编辑  收藏  举报