专栏文章

题解:CF1889D Game of Stacks

CF1889D题解参与者 2已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@miq732ms
此快照首次捕获于
2025/12/04 00:01
3 个月前
此快照最后确认于
2025/12/04 00:01
3 个月前
查看原文
发现其他题解都没有仔细地讲解实现。
所以特地来补充一下造福后人。

直接暴力深搜,建立一个栈 st,每遍历到一个栈,就将栈的编号塞入 st 中。
如果第 ii 个栈的栈顶为 ci,jc_{i,j},那么就建立一条 ici,ji\to c_{i,j} 的边,并走过去。
此时有四种情况
  • ci,jc_{i,j} 个栈已经为空,那么所有留存在 st 中的栈的答案均为 ci,jc_{i,j}
  • ci,jc_{i,j} 个栈已经记录了答案 ansci,jans_{c_{i,j}},那么所有留存在 st 中的栈的答案均为 ansci,jans_{c_{i,j}}
  • ci,jc_{i,j} 个栈已经被遍历过了,那么对 st 进行弹栈操作直到 ci,jc_{i,j} 被弹出,对于每个被弹出的栈的编号 stist_i,我们将第 stist_i 个栈的栈顶永久性的弹出(因为显然此时构成了一个,无论你从这个环的哪一处开始遍历,这一个环都一定会被消去)。
  • 否则,继续搜索。
显然总复杂度为 O(n+ki)O(n+\sum k_i)
CPP
int n,k[N],ans[N];
stack<int> c[N],st;
bool vis[N];
int dfs(int u){
	if(ans[u]) return ans[u];
	if(vis[u])
		while(1){
			int v=st.top(); st.pop();
			vis[v]=0;
			c[v].pop();
			if(v==u) break;
		}
	vis[u]=1,st.push(u);
	if(c[u].empty()) return u;
	return dfs(c[u].top());
}
void solve(){
	cin>>n;
	for1(i,1,n){
		cin>>k[i];
		for1(j,1,k[i]){
			int _c;
			cin>>_c;
			c[i].push(_c);
		}
	}
	for1(i,1,n){
		if(!ans[i]){
			ans[i]=dfs(i);
			while(!st.empty())
				ans[st.top()]=ans[i],st.pop();
		}
		cout<<ans[i]<<" ";
	}
	return ;
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...