Codeforces Round #693 (Div. 3) G - Moving to the Capital 最短路+dp

原题链接:https://codeforces.ml/contest/1472/problem/G

目录

题意

有n个点,m条单项边,每个点上有三个操作

  1. 如果dis[u] < dis[v],可以直接从u到v,可以进行无限次操作
  2. 如果dis[u] >= dis[v],可以从u到v,只能操作一次
  3. 待在u节点不动

问从i节点出发能到距离1节点最近的距离是多少?

分析

如果直接建图,然后每个点上遍历一次肯定可以求出答案,但时间会超时,因此考虑记录已经遍历到的节点。

先预处理一遍最短路,用bfs就可以实现

接着设一个状态f[x][2]表示从x节点出发可以到距离1最近的位置是多少,后面0代表没用过2操作,1代表已经用了2操作。

然后就是状态转移的过程

  1. 操作1:f[x][flag] = min(f[x][flag], dfs(v, flag))
  2. 操作2:f[x][flag] = min(f[x][flag], dfs(v, 1))
  3. 操作3:f[x][flag] = min(f[x][flag], dis[x])

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 100, M = 5e5 + 5, INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int f[N][2], dis[N], vis[N];
vector<int> g[N];
void bfs(int s) {
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    queue<int> q; q.push(s); dis[s] = 0;
    while (q.size()) {
        int u = q.front();
        q.pop();
        if (vis[u]) continue;
        vis[u] = 1;
        for (auto v : g[u]) {
            dis[v] = min(dis[v], dis[u] + 1);
            q.push(v);
        }
    }
}

int dfs(int x, int flag) {
    if (f[x][flag] != INF) return f[x][flag];
    f[x][flag] = dis[x];
    for (auto v : g[x]) {
        if (dis[v] > dis[x]) {
            f[x][flag] = min(f[x][flag], dfs(v, flag));
        } else {
            if (!flag) {
                f[x][flag] = min(f[x][flag], dfs(v, 1));
            }
        }
    }
    return f[x][flag];
}
void solve() {
    int T; cin >> T; while (T--) {
        int n, m; cin >> n >> m;
        for (int i = 1; i <= n; i++) g[i].clear();
        for (int i = 1; i <= m; i++) {
            int u, v; cin >> u >> v;
            g[u].push_back(v);
        }
        bfs(1);
        memset(f, 0x3f, sizeof f);
        for (int i = 1; i <= n; i++) {
            cout << dfs(i, 0) << " ";
        }
        cout << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif
    solve();
}
上一篇:[CISCN2019 总决赛 Day2 Web1]Easyweb(预期解)


下一篇:转:UI自动化学习-PageObject六大原则