食物链(三类动物)

用一个relation[]来存储关系,0代表同类,1代表吃父节点,2代表被父节点吃。将其想象成一棵树,这些动物相当于树上的不同节点,则他们之间必定有某种关系,即上面的0,1,2。

我们利用并查集中的find函数,在将树中每个节点的父节点指向根节点的同时,更新其与根节点的关系。

这样的话,我们示例验证a和b是否是同类:1.判断根节点是否相同。2.a和b与根节点的关系是否相同。若1,2皆满足则a和b一定相同。

或者我们根据所描述的a和b是同类,来进行更新节点的父节点的操作,同时更新节点的relation[]的操作(父节点变了,relation[]一定要更新)。

1.把a的父节点指向b的父节点( p[find(a) ]=find(b) )。

2.有relation[a] + relation[root_a] = relation[b],上面的等式是我们根据a和b是同类推出来的,root_a的代表是a原先的父节点,且只有relation[root_a]是未知的,于是就有

relation[root_a]=(relation[b]-relation[a]+3)%3

#include<iostream>
using namespace std;

const int M = 1e5 + 10;

int N, K;
int p[M], relation[M];//p为父节点数组,relation是与父节点的关系数组
int temp;

int find(int x)
{
	if (p[x] != x)
	{
		int old_p = p[x];
		p[x] = find(p[x]);
		relation[x] = (relation[x] + relation[old_p]) % 3;//路径压缩时更新关系
	}
	return p[x];
}

int main()
{
	scanf_s("%d%d", &N, &K);
	//初始化
	for (int i = 1; i <= N; i++)
	{
		p[i] = i;//开始时每个节点的父节点是它本身
		relation[i] = 0;//自己是自己的同类
	}
	int D, a, b;
	
	while (K--)
	{
		scanf_s("%d%d%d", &D, &a, &b);
		//检查输入是否越界
		if (a > N || b > N)                        //要加continue,跳出当前循环,进行下一次循环
		{
			temp++;
			continue;
		}

		int root_a = find(a);
		int root_b = find(b);

		if (D == 1)//说a和b时同类,接下来验证真假,或者根据这句话更新a和b的关系
		{
			if (root_a == root_b)
			{
				if (relation[a] != relation[b])temp++;
			}
			else
			{
				p[find(a)] = find(b);//更新a的父节点
				relation[root_a] = (relation[b] - relation[a] + 3) % 3;//得到a原来的祖先节点到他们新的祖先节点的关系
			}
		}
		if (D == 2)//说a吃b
		{
			if (a == b)//自己不能吃自己
			{
				temp++;
				continue;//依旧不能漏掉continue
			}
			if (root_a == root_b)
			{
				if ((relation[a] - relation[b] + 3) % 3 != 1)temp++;//判断a是否吃b,即差值模三是否为1
			}
			else
			{
				p[find(a)] = find(b);//更新a的父节点
				relation[root_a] = (relation[b] - relation[a] + 1 + 3) % 3;
			}
		}

	}
	printf("%d\n", temp);
	return 0;
}

acwing240 算法打卡,属于并查集的运用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值