📅  最后修改于: 2023-12-03 15:28:49.270000             🧑  作者: Mango
这是一道使用 DFS 进行模拟的题目。
题目传送门:「门|门模拟 2017」第 57 题
给出 $n$ 个正整数,表示由 $n$ 个门相连成的环。现在有 $m$ 次询问,每次询问给出三个整数 $a$、$b$、$c$,意思是从 $a$ 号门进入,一直顺时针走,走到第一个编号为 $b$ 的门时,如果这个门的状态为 $0$,那就全都变成 $1$,否则不变化,最后问走 $c$ 步之后停在哪一个门上。每次询问保证 $1 \leq a, b \leq n$,$a \neq b$,$1 \leq c \leq 10^9$。
我们可以用一个 vector 存储每个门可以到达的下一个门的编号,然后用一个 bool 数组表示每个门的状态。
对于每一次询问,都可以将从 $a$ 号门开始可到达的所有门的状态进行改变。暴力模拟改变每个门的状态,然后依次走 $c$ 步即可。注意需要将 $c$ 取模 $n$,因为这 $n$ 个门是构成一个环的。
// -*- coding: utf-8 -*-
#include<bits/stdc++.h>
#define rei register int
#define maxn 505000
#define pb push_back
using namespace std;
vector<int> t[maxn];
bool vis[maxn];
void dfs(int u) {
for (rei i = 0; i < t[u].size(); ++i) {
int v = t[u][i];
if (!vis[v]) {
vis[v] = 1;
dfs(v);
}
}
}
int main() {
// freopen("P4474.in", "r", stdin);
// freopen("P4474.out", "w", stdout);
ios::sync_with_stdio(false);
int n, m, k;
cin >> n >> m >> k;
for (rei i = 1; i <= m; ++i) {
int x, y;
cin >> x >> y;
t[x].pb(y);
t[y].pb(x);
}
memset(vis, 0, sizeof vis);
dfs(k);
int pos = k;
for (rei i = 1; i <= n; ++i) {
if (vis[i] && i != k) {
pos = i;
break;
}
}
int h = 0;
for (rei i = 1, x, y; i <= n; ++i) {
cin >> x >> y;
int t = pos;
for (rei j = 1; j <= y % n; ++j) {
t = t == n ? 1 : t + 1;
if (t == x) {
if (!vis[x])
memset(vis, 0, sizeof vis);
dfs(x);
vis[x] = 1;
vis[t] = !vis[t];
}
}
cout << t << "\n";
}
return 0;
}
以上代码是 C++ 语言编写的。
对于每次询问,我们都需要深度优先搜索,时间复杂度为 $O(n)$。对于每个门的状态的变化,最多需要改变 $n$ 个门的状态,所以时间复杂度为 $O(n^2)$。
总时间复杂度为 $O(n^3)$。但是由于题目给定了 $c$ 的范围,所以实际时间复杂度较小。