之后,你计划在上厕所的时候溜出去,利用助手留下来的领带找到有保险箱的房间。保险箱藏在房间里,所以你进入带有保险箱的房间时,必须依靠领带识别这个房间;此外,由于“上厕所”时间过长会被发现,你必须尽快找到保险箱。你最多可以走过 d+30 扇门,其中 d 是你的初始位置到保险箱所在位置的最短路径上的门数量。若重复穿过同一扇门,则每次都计入。
int n, safe; int p[kMaxN], sz[kMaxN], mx[kMaxN]; bool vis[kMaxN]; std::vector<int> G[kMaxN], rt;
voiddfs1(int u, int fa){ sz[u] = 1, mx[u] = 0; for (auto v : G[u]) { if (v == fa) continue; dfs1(v, u); sz[u] += sz[v], mx[u] = std::max(mx[u], sz[v]); } mx[u] = std::max(mx[u], n - sz[u]); if (mx[u] <= n / 2) rt.emplace_back(u); }
voiddfs2(int u, int fa){ p[u] = fa; for (auto v : G[u]) { if (v == fa) continue; dfs2(v, u); } }
voiddfs3(int u, int fa){ vis[u] = 1; for (auto v : G[u]) { if (v == fa || vis[v]) continue; if (visit(v)) returndfs3(v, u); elsevisit(u); } }
std::vector<int> mark(std::vector<std::pair<int, int>> F, int safe){ n = (int)F.size() + 1; std::vector<int> vec(n, 0); for (int i = 1; i <= n; ++i) G[i].clear(); for (auto [u, v] : F) G[u].emplace_back(v), G[v].emplace_back(u); rt.clear(), dfs1(1, 0), dfs2(rt[0], 0); for (int i = safe; i; i = p[i]) { vec[i - 1] = 1; if (rt.size() == 2 && (i == rt[0] || i == rt[1])) break; } return vec; }
voidlocate(std::vector<std::pair<int, int>> F, int cur, int t){ n = (int)F.size() + 1; for (int i = 1; i <= n; ++i) G[i].clear(), vis[i] = 0; for (auto [u, v] : F) G[u].emplace_back(v), G[v].emplace_back(u); rt.clear(), dfs1(1, 0), dfs2(rt[0], 0); for (int i = 1; i <= n; ++i) std::sort(G[i].begin(), G[i].end(), [&] (int x, int y) { return sz[x] > sz[y]; }); for (; p[cur] && !t; t = visit(cur = p[cur])) vis[cur] = 1; vis[cur] = 1; if (!t) assert(cur == rt[0]), visit(cur = rt[1]); vis[cur] = 1; dfs3(cur, p[cur]); }