Teleporter Setting(最短路,思维)

题意

给定一个\(N\)个点\(M\)条边的无向图,每条边用\((u_i, v_i)\)来表示,边权为\(1\)

其中一些边是未定的,如:\((u_i, 0)\)表示一个点是\(u_i\),另一个点未定。

对于\(i = 1, 2, \dots, N\),问:当未定边的另一个点全都是\(i\)时,从\(1\)\(N\)的最短距离是多少?

题目链接:https://atcoder.jp/contests/abc257/tasks/abc257_f

数据范围

\(2 \leq N \leq 3 \times 10^5\)
\(1 \leq M \leq 3 \times 10^5\)

思路

\(0\)号点作为额外的点。当\(i = k\)时,问题转化为在\(0\)\(k\)之间加一条边权为\(0\)的边,求\(1\)\(N\)的最短路。

如果不使用加的这条边,那么答案为\(dist_{1,N}\)。如果使用这条边,那么必然经过\(0\)\(k\)两个点,因此答案为\(\min (dist_{1, 0} + dist_{k, N}, dist_{1, k} + dist_{0, N})\)

因此分别以\(1\)\(N\)为起点,跑BFS即可。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 300010, M = 2 * N;

int n, m;
int h[N], e[M], ne[M], idx;
int dist1[N], dist2[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void bfs(int dist[], int u)
{
    queue<int> que;
    que.push(u);
    for(int i = 0; i <= n; i ++) dist[i] = 1e9;
    dist[u] = 0;
    while(que.size()) {
        int t = que.front();
        que.pop();
        for(int i = h[t]; ~i; i = ne[i]) {
            int j = e[i];
            if(dist[j] > dist[t] + 1) {
                dist[j] = dist[t] + 1;
                que.push(j);
            }
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    for(int i = 0; i < m; i ++) {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b), add(b, a);
    }
    bfs(dist1, 1), bfs(dist2, n);
    for(int i = 1; i <= n; i ++) {
        int ans = min(dist1[n], min(dist1[0] + dist2[i], dist1[i] + dist2[0]));
        if(ans >= 1e9) ans = -1;
        printf("%d ", ans);
    }
    printf("\n");
    return 0;
}
posted @ 2022-06-27 10:57  pbc的成长之路  阅读(17)  评论(0编辑  收藏  举报