AtCoder-abc257_f Teleporter Setting
Teleporter Setting
bfs
先构建一个 0 号虚拟点,最后再遍历这个点是其他的点
答案有两种来源:
-
本身从 1 直接到达 n(可经过 0 号虚拟点)
-
经过 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;
}