游戏(并查集)

题目大意

  • Mirko 和 Slavko 爱玩弹球戏。在一个令人激动的星期五,Mirko 和 Slavko 玩了一把弹球游戏。Mirko 构建一个有向图,所有顶点最多有 1 条出边。弹球从 1个顶点出发可以沿着一条边移动到它的邻接点,只要它存在,而且它会继续移动到后者的邻接点去,直到最后到达一个找不到出边的顶点才停下来。如果不存在这样的点,弹球可能无限运动下去。

  • 为了确信 Slavko理解游戏的规则,Mirko 将发起一系列询问,询问的类型如下:

  • 1 X:除非弹球陷入循环,弹球从 X 出发,最终将在哪个点停下来。

  • 2 X:删除 X 的出边(保证该边总是存在)

  • 注意:询问是按顺序执行的。

输入格式

  • 第一行包含一个正整数 N(1<=N<=300000),表示图的定点数。
  • 第二行包含由空格隔开 N 个正整数,第 i 个数表示从 i 顶点可以通过出边到达的定点编号。0表示该点没有出边。
  • 接下来的一行包含 1 个整数 Q(1<=Q<=300000),表示询问的次数。格式如上所示。

输出格式

  • 对于第 1 类询问,输出弹球停止时所在顶点编号,每行 1 个,按照查询的顺序输出。如果弹球无法停止,则输出 CIKLUS.

样例

样例输入

3
2 3 1
7
1 1
1 2
2 1
1 2
1 1
2 2
1 2

样例输出

CIKLUS
CIKLUS
1
1
2

算法分析

  • 显然是并查集(没错我又显然了)
  • 其实暴力算法很好想吧 每次dfs 用vis数组维护是否访问过 如果在一次dfs中访问到了vis标记的点就输出CIKLUS 如果访问到了没有出边的点就输出这个点
  • 但是这样暴力有个很显然的问题 三十万的数据 每次都要初始化一个三十万的数组vis 显然是会T的(我又双显然了)
  • 所以想一想就会想到用并查集维护使得在O(1)时间内完成查询操作 但是显然并查集不能进行删除操作(又双叒显然),因为并查集路径压缩之后是不知道跳到祖先节点的路径的 所以如果进行删除之后当前节点的fa仍然是祖先 相当与没有删除
  • 那该怎么做呢? 先不进行路径压缩,把所有的父亲节点做一次备份,然后把能删除的边都删除,然后后面输入询问的时候把询问存下来 然后倒着跑一遍 如果遇到2的操作就把那个边加上,遇到1就把答案存起来 最后正序输出
  • 关于为什么可以这么做,其实是一个很显然的问题(又双叒叕),因为如果正常顺序的话 ,在当前2操作之前的所有点,都是有x这条边的,而之后的所有点都是没有的,所以就可以了
  • 那如何判环呢? 在最后路径压缩的时候 一开始是一个一个找的父亲 我们用cnt数组记录dfs递归的深度 如果dfs最后超过了n(n个点最多递归n次 如果多了就是有环)就将当前节点的目标位置设置为0(即为环)

代码展示:



#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10,maxm = 2e4+10;

int f[maxn],ff[maxn];
int a[maxn],flag[maxn];
int n;

int find(int x,int cnt){if(cnt > n)return f[x] = 0;return x == f[x] ? x : f[x] = find(f[x],++cnt);}//cnt判环

int main(){
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)f[i] = i;
	for(int i = 1;i <= n;++i){int x;scanf("%d",&x);if(x != 0)f[i] = ff[i] = x;}
	int k;scanf("%d",&k);
	for(int i = 1;i <= k;++i){scanf("%d%d",&flag[i],&a[i]);if(flag[i] == 2)f[a[i]] = a[i];}//断边
	for(int i = k;i >= 1;--i){
		if(flag[i] == 1)a[i] = find(a[i],0);//查询
		if(flag[i] == 2)f[a[i]] = ff[a[i]];//加边
	}
	for(int i = 1;i <= k;++i){
		if(flag[i] == 1 &&  a[i])printf("%d\n",a[i]);//输出
		if(flag[i] == 1 && !a[i])printf("CIKLUS\n");//没找到
	}
	return 0;
}


posted @ 2020-07-16 21:12  HISKrrr  阅读(201)  评论(0编辑  收藏  举报