首页 > 其他分享 >NKOJ 2107 【并查集】可爱的猴子

NKOJ 2107 【并查集】可爱的猴子

时间:2024-12-14 10:09:52浏览次数:10  
标签:int fy NKOJ 查集 getf 400005 fx now 2107

NKOJ 2107 【并查集】可爱的猴子

思路:普通并查集+图的遍历更新答案

实现方法

  • 首先使用时光倒流思想解决删边的问题。
  • 注意提前把没有删过的边提前建上。
  • 接着用一个图记录猴子之间的拉手关系,每次要更新答案时都遍历与当前节点连着的节点将其答案更新,只有在 \(1\) 号节点与当前节点断开时才更新答案。

代码

#include<cstdio>
using namespace std;
int n,m,cnt;
int mks[400005][5],ltg[400005][5],last[400005];
int del[400005][5],ans[400005],vis[400005];
struct node{int pre,to;}adj[400005];
void Add(int x,int y){adj[++cnt].to=y,adj[cnt].pre=last[x],last[x]=cnt;}
int f[400005];
int getf(int x){
	if(x==f[x]) return f[x];
	return f[x]=getf(f[x]);
}
void dfs(int x,int now){
	ans[x]=now;
	vis[x]=1;
	for(int i=last[x];i;i=adj[i].pre){
		int lzh=adj[i].to;
		if(vis[lzh]==0){
			dfs(lzh,now);
		}
	}
	vis[x]=0;
}
void merge(int x,int y,int now){
	int fx=getf(x),fy=getf(y);
	if(fx==fy) return;
	if(now==-1){
		f[fx]=fy;
		return;
	}
	if(fx==getf(1)) dfs(fy,now);
	else if(fy==getf(1)) dfs(fx,now);
	f[fx]=fy,Add(x,y),Add(y,x);
}
/*错误示范
void merge(int x,int y,int now){
	int fx=getf(x),fy=getf(y);
	if(fx==fy) return;
	if(fx==getf(1)&&now!=-1) dfs(fy,now);
	else if(fy==getf(1)&&now!=-1) dfs(fx,now);
	f[fx]=fy,Add(x,y),Add(y,x);//加第二次
}
*/
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) f[i]=i;
	for(int i=1;i<=n;i++) scanf("%d%d",&mks[i][1],&mks[i][2]);
	for(int i=1;i<=m;i++) scanf("%d%d",&ltg[i][1],&ltg[i][2]),del[ltg[i][1]][ltg[i][2]]=1;
	for(int i=1;i<=n;i++){
		if(mks[i][1]!=-1&&!del[i][1]) merge(i,mks[i][1],-1),Add(i,mks[i][1]),Add(mks[i][1],i);//加一次
		if(mks[i][2]!=-1&&!del[i][2]) merge(i,mks[i][2],-1),Add(i,mks[i][2]),Add(mks[i][2],i);
	}
	for(int i=m;i>=1;i--){
		int x=ltg[i][1],y=mks[ltg[i][1]][ltg[i][2]];
		merge(x,y,i);
	}
	for(int i=1;i<=n;i++){
		printf("%d\n",ans[i]-1);
	}

	return 0;
}

注意事项

  1. 一定注意在 merge 的时候注意不要重复加边,会T。

标签:int,fy,NKOJ,查集,getf,400005,fx,now,2107
From: https://www.cnblogs.com/hsr-ray-blog/p/18606424

相关文章

  • NKOJ 1206 【NOI2002 Day1 T1】银河英雄传说
    NKOJ1206【NOI2002Day1T1】银河英雄传说思路:和NKOJ2281一样实现方法移动操作完全一样。计算操作的区别在于,一个是直接输出到根节点的距离,另一个实际上是前缀和思想,用\(x\)到根的距离减去\(y-1\)到根的距离,就是\(x\simy\)之间的距离。代码#include<cstdio>#in......
  • NKOJ 1407 地毯填补问题
    NKOJ1407地毯填补问题思路分治算法经典题。实现方法把公主看成障碍物,填的地毯也是障碍物。观察题目发现迷宫大小为\(2^k\times2^k\)格,每次正好可以四等分。每次填充的地毯正好填三格,正好留下一格障碍物。代码#include<bits/stdc++.h>#defineintlonglongusi......
  • NKOJ 3631 密码锁
    NKOJ3631密码锁思路BFS经典题。实现方法用一个结构体存储当前密码锁的状态和已经走过的步数。将开始的状态入队。每次取出队首,枚举所有可能情况。每一位的上下拨动。每两位之间的交换。共\(11\)种情况。给入队的情况打标记。代码#include<map>#include<qu......
  • NKOJ 2110 美丽的星空
    NKOJ2110美丽的星空思路洪水填充(BFS)+多边形全等的判定。实现方法这道题比较复杂,分为三个步骤。用BFS求出有哪些星座并编号。两两判全等。多边形的全等判定定理:如果两多边形每两个点之间的距离和相等,则它们全等。如果两个多边形全等,就将新的打上旧的的标记。......
  • XDOJ 735 最小生成树 (Kruskal+并查集)
    标题最小生成树时间限制2S内存限制10000Kb问题描述:用克鲁斯卡尔(Kruskal)算法求无向网的最小生成树。输入:输入数据第一行为两个正整数n(1<n<=30)和m(1<m<100),分别表示顶点数和边数。后面紧跟m行数据,每行数据是一条边的信息,包括三个数字,分别表示该边的两个顶点和边上的权值......
  • 并查集模板(map保存负数下标)
    classSolution{unordered_map<int,int>fa,rank;voidinit(unordered_set&set){for(constauto&num:set){fa[num]=num;rank[num]=1;}}intfinds(intx){if(x!=fa[x]){fa[x]=finds(fa[x]);}returnfa[x];}voidunions(intx,inty){introotx=f......
  • 【唐叔学算法】第八天:并查集-图论连通性的大杀器
    你是否曾为如何高效地解决图论中的连通性问题而烦恼?并查集算法,就像一张无形的网,能帮你轻松连接所有节点。今天,就让我们一起揭开并查集算法的神秘面纱,探索它在Java编程中的应用。并查集是什么?并查集(Union-Find)是一种数据结构,用于处理一些不交集的合并及查询问题。它支持两......
  • 并查集学习笔记
    一、例题引入洛谷P3367【模板】并查集题目描述如题,现在有一个并查集,你需要完成合并和查询操作。输入格式第一行包含两个整数$N,M$,表示共有$N$个元素和$M$个操作。接下来$M$行,每行包含三个整数$Z_i,X_i,Y_i$。当$Z_i=1$时,将$X_i$与$Y_i$所在的集合合并。......
  • 每日一道算法题之并查集之移除最多的同行或同列石头
    importjava.util.HashMap;classSolution{publicstaticHashMap<Integer,Integer>row=newHashMap<>();publicstaticHashMap<Integer,Integer>col=newHashMap<>();publicstaticintMAXN=1001;publicstati......
  • 每日一道算法题之并查集之岛屿数量
    classSolution{publicstaticintMAXN=90001;publicstaticint[]f=newint[MAXN];publicstaticintn=0;publicstaticintunion_count=0;publicstaticbooleanisSameSet(inti,intj){returnfind(i)==find(j);......