并查集的应用

带权并查集

T1.银河英雄传说

题意分析:

题目中所说的列我们可以将其看成一个集合,其中每一艘战舰之间均有关系,由此可以得出,战舰之间的关系是具有传递性的,所以我们可以用并查集来建立战舰之间关系的树形结构

对于每次的询问,可以维护一个数组d,表示当前元素到集合代表的距离(边权为1)

所以,询问i与j之间相隔的战舰数量,实际可以看作:i与j之间的距离 - 1

所以,本题的重点在于维护d数组

1.初始化:自己到自己的距离为0

2.查询:每次进行查询时,我们都需要将查询点的 d[x] 累加查询其祖先路径上所有的d

3.合并:将x集合合并在y集合,此时我们还需要一个size数组维护每个集合内的元素数量,并对d数组赋值

代码实现:

初始化:

void MakeSet() {
	for (int i = 1; i < SIZE; i ++ ) {
		fa[i] = i;
		d[i] = 0;
		size[i] = 1;
	}
}

路径压缩:

int FindSet(int x) {
	if (x == fa[x]) return x;
	int root = FindSet(fa[x]);// 路径压缩时更新 
	d[x] += d[fa[x]]; // d[x], x直接指向树根的边权和 
	return fa[x] = root;
}

合并:

void UnionSet(int x, int y) {
	x = FindSet(x), y = FindSet(y);
	fa[x] = y;
	d[x] = size[y];
	size[y] += size[x];
	size[x] = 0;
	return;
}

扩展域并查集

T2.食物链

题意分析:

根据题目,A吃B, B吃C,C吃A

对于每一个元素,可以扩展成三个部分,本身,猎物,天敌

将它们分别放在(1, n), (n + 1, 2n),(2n + 1, 3n)

所以在判断元素x与y的关系时,有以下可能:

  1. 如果给出x与y是同类,那么x + n, y + n是同类;x + 2n, y + 2n是同类

2.如果x会吃y,那么y是x的猎物,所以有:

x + n与y是同类

x + 2n与y + n是同类

x与y + 2n是同类

代码实现:

void check(int d, int x, int y, int n) {
	if (d == 2 && x == y)  {
		ans ++;
		return;
	}
	if ((x > n) || (y > n)) {
		ans ++;
		return;
	} 
	if (d == 2) {
      	// 如果x吃y,那么只能是x与y + 2n是同类
		if (FindSet(x) == FindSet(y) || FindSet(x) == FindSet(y + n)) {
			ans ++;
		}
		else {
			UnionSet(x, y + n * 2);
			UnionSet(x + n * 2, y + n);
			UnionSet(x + n, y);
		}	
	} else {
      	// 如果x与y是同类,那么只能是y与x是同类
		if (FindSet(x + n) == FindSet(y) || FindSet(x + 2n) == FindSet(y)) {
			ans ++;
		}	
		else {
			UnionSet(x, y);
			UnionSet(x + n, y + n);
			UnionSet(x + n * 2, y + n * 2);
		}	
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值