题解 CF1889D 【Game of Stacks】
好优雅的题啊 /tyt
首先考虑
转化为图论模型,连边 init(i) 的返回值为从
注意到此时的图为内向基环树,于是答案为
乍看没有什么启发性,因为推广到
但注意到对于基环树的情况,我们实际上可以忽略环。对于一般情况,若在中间出现环
于是我们 dfs 时用栈维护走过的点即可。时间复杂度为
代码:
#include <iostream>
#include <stack>
#include <cstdio>
using namespace std;
int top;
int c[100007], stk[100007], ans[100007];
bool vis[100007];
stack<int> s[100007];
inline int read(){
int ans = 0;
char ch = getchar();
while (ch < '0' || ch > '9'){
ch = getchar();
}
while (ch >= '0' && ch <= '9'){
ans = ans * 10 + (ch ^ 48);
ch = getchar();
}
return ans;
}
int dfs(int u){
if (ans[u] != 0) return ans[u];
if (vis[u]){
while (true){
int cur = stk[top--];
vis[cur] = false;
s[cur].pop();
if (cur == u) break;
}
}
vis[u] = true;
stk[++top] = u;
if (s[u].empty()) return u;
return dfs(s[u].top());
}
int main(){
int n = read();
for (int i = 1; i <= n; i++){
int k = read();
for (int j = 1; j <= k; j++){
int c = read();
s[i].push(c);
}
}
for (int i = 1; i <= n; i++){
if (ans[i] == 0){
int cur_ans;
top = 0;
cur_ans = dfs(i);
for (int j = 1; j <= top; j++){
ans[stk[j]] = cur_ans;
}
}
cout << ans[i] << " ";
}
return 0;
}