并查集OJ做题报告

并查集

洛谷P3367

模板并查集

以后要注意的:

  1. scanf函数括号里面要写好,先双引号" " ,再用逗号,将输入内容和变量分开

洛谷P1525

关押罪犯

学到了:

  1. sort函数的第三个参数,该参数是一比较参数,决定排序完数据是升序还是降序
cpp 复制代码
bool cmp(int a,int b){
	return a>b;//可以理解为当a>b时把a放在b前面,就是升序
	//return a<b;可以理解为当a<b时把a放在b前面,就是降序
}
  1. 结构体数组排序
    1. 先定义结构体
cpp 复制代码
struct node{
	int a,b,c;
}x[10];
  1. 输入数据
cpp 复制代码
for(int i=1;i<=m;i++){
		scanf("%d %d %d",&x[i].a,&x[i].b,&x[i].c);
		} 

3.设立比较条件

  • 一级排序(将c从大到小排序)
cpp 复制代码
bool cmp(node i,node j){
	return i.c>j.c;
}
  • 二级排序(c相等的情况下,按照b大小来从小到大排序)
cpp 复制代码
bool cmp(node i,node j){
	if(i.c==j.c){
		return i.b>j.b;
	}else{
		return i.c>j.c;
	}
}

以后要注意的:

  • 种类并查集就是找出有哪些不同种类(不同集合)
  • 在一数组上划分不同的状态(比如i为正状态,则i+n为反状态,两者不共存)
  • 当题目要求分开x和y时,我们就需要合并x和y的反状态,y和x的反状态
  • 判断是否已经区分就是查看是否在一个集合(普通并查集),找父节点

洛谷CF776D

CF776D The Door Problem

思路:

怎么想到用并查集的?

  1. 我们已经得知每盏灯的初始状态和哪两个开关控制它。

  2. 首先分类讨论:

    • 如果最开始这盏灯是开着的,那么这两个开关应该做出同样的操作,即要么全按,要么全不按。

    • 如果最开始这盏灯是关着的,那么这两个开关应该做出不同的操作,即一个按一个不按。

    • 转化一个思路,就变成了有 m 个数,其中有 n 个关系,有些关系是两个数要一样,有些关系是两个数要不一样,问是否合理。

  3. 维护开与关的关系,我们想到了并查集。

该题目最重要的一句话:每扇门恰好被两个开关控制

而每扇门只有两个状态:

  1. 0状态,房间门是锁着的
  2. 1状态,房间门的开着的

依题意现在每一扇门对应两个钥匙,设门为开 的状态为(u,v),设门为关 的状态为(u+m,v+m)且一共有m个开关数,则:

  • 对于开着的门:

    合并(u,v)(u+m,v+m)

    • 同种状态钥匙开一遍才能保持门是"开"的状态
  • 对于关着的门:

    合并(u,v+m),(u+m,v)

    • 不同种状态的钥匙开一遍才能保证门是关着的

当合并完之后,我们只需要遍历所有开关数 i ,当发现ii+m在同一集合,则输出 "NO",因为一把钥匙只能有使用或不使用的状态.所以如果ii+m在一个并查集内,这是不合法的

这一流程用并查集文字意思就是:

  • 遍历每一个门的时候赋予每一个开关开或不开的状态,当有一个开关矛盾了(就是开和不开同时需要满足),则依题意输出 "NO"。

这里的输入流程比较麻烦:

  1. 输入房间数和开关数
  2. 输入房间状态(基于房间数)
  3. 输入控制房间数量
  4. 输入钥匙控制房间的编号(基于第3点)
    • 这里要用一个结构体数组来存数据,数组下标是房间号,结构体里面是能控制对应房间号的两个钥匙
cpp 复制代码
struct key{
	int a,b;
}x[200005];
for(int i=1;i<=m;i++){		//i是开关编号 
		int c;
		scanf("%d",&c);			//控制的房间数量 
		for(int j=1;j<=c;j++){
			int d;
			scanf("%d",&d);		//被控制的房间编号
			if(x[d].a==0){
				x[d].a=i; 		//房间编号d由2个开关中的i开关控制 
			}else{
				x[d].b=i;
			}
		}
	}
}

以后要注意的:

  1. 处理并查集时始终用一个函数来合并集合,避免直接修改父节点数组(或者修改完父节点数组后再次重新查找父节点),因为这会破坏路径压缩,导致循环引用或造成错误的集合关系,破坏了并查集结构
相关推荐
ShineWinsu2 小时前
对于模拟实现C++list类的详细解析—上
开发语言·数据结构·c++·算法·面试·stl·list
程序员酥皮蛋2 小时前
hot 100 第二十九题 29.删除链表的倒数第 N 个结点
数据结构·算法·leetcode·链表
stripe-python2 小时前
十二重铲雪法(下)
c++·算法
I Promise342 小时前
BEV视角智驾方案全维度发展梳理
人工智能·算法·计算机视觉
化学在逃硬闯CS3 小时前
【Leetcode热题100】108.将有序数组转换为二叉搜索树
数据结构·c++·算法·leetcode
追随者永远是胜利者3 小时前
(LeetCode-Hot100)5. 最长回文子串
java·算法·leetcode·职场和发展·go
tankeven3 小时前
HJ86 求最大连续bit数
c++·算法
ValhallaCoder3 小时前
hot100-回溯II
数据结构·python·算法·回溯
追随者永远是胜利者3 小时前
(LeetCode-Hot100)19. 删除链表的倒数第 N 个结点
java·算法·leetcode·链表·go