【Codeforces Round #693 (Div. 3) G】Moving to the Capital
阿新 • • 發佈:2021-01-11
題目連結
翻譯
注意是有向圖,不然這題讀起來會覺得題目很奇怪。。
題解
bfs
求最短路 d[1..n]
,然後對於 \(d_i<d_j\) 的邊連實線,否則連虛線。
就可以做 dp
了,對於實線 dp[x] = min(dp[x],dp[y])
,對於虛線 dp[x] = min(dp[x],d[y])
。
虛線只能走一次嘛。然後實線還能順著往下走。妥妥的記憶化,當然不要忘了待在原地不動的情況,對應 \(dp[x]=min(dp[x],d[x])\)
程式碼
#include <bits/stdc++.h> #define LL long long using namespace std; const int N = 2e5; const LL MOD = 1e9 + 7; const int K = 5000; int n, m, d[N+10],dp[N+10]; vector<int> g[3][N + 10]; queue<int> dl; void bfs() { for (int i = 1; i <= n; i++) { d[i] = n + 1; } d[1] = 0; dl.push(1); while (!dl.empty()) { int x = dl.front(); dl.pop(); int len = g[0][x].size(); for (int y : g[0][x]) { if (d[y] == n + 1) { d[y] = d[x] + 1; dl.push(y); } } } } int dfs(int x) { if (dp[x] != n + 1) { return dp[x]; } //實線可以任意走。 for (int y : g[1][x]) { dp[x] = min(dp[x], dfs(y)); } //虛線只能走一次。 for (int y : g[2][x]) { dp[x] = min(dp[x], d[y]); } //待在原地 dp[x] = min(dp[x], d[x]); return dp[x]; } int main() { #ifdef LOCAL_DEFINE freopen("in.txt", "r", stdin); #endif ios::sync_with_stdio(0), cin.tie(0); int T; cin >> T; while (T--) { cin >> n >> m; for (int i = 1; i <= n; i++) { for (int j = 0; j < 3; j++) { g[j][i].clear(); } } for (int i = 1; i <= m; i++) { int x, y; cin >> x >> y; g[0][x].push_back(y); } bfs(); for (int x = 1; x <= n; x++) { for (int y : g[0][x]) { if (d[y] > d[x]) { g[1][x].push_back(y); } else { //虛線 g[2][x].push_back(y); } } } for (int i = 1; i <= n; i++) { dp[i] = n + 1; } for (int i = 1; i <= n; i++) { if (dp[i] == n + 1) { dp[i] = dfs(i); } } for (int i = 1; i <= n; i++) { cout << dp[i] << " "; } cout << endl; } return 0; }