并查集代码+杭电1213、杭电1232

前言


在这里插入图片描述
大家好呀,周六啦,周末当然是要代码+音乐啊(刚打完王者😁😁),记录下昨晚寝室的happy:回味无穷的美食😍+惊悚电影🤪+快乐五排无限上分😁.
好啦,这篇博客是想再复习下昨天的算法课内容.

✈️✈️问题:

问题:有n个城市,通过输入俩个数a,b,表示a->b是联通的,求最后联通的个数。

✈️✈️解决:

开一个数组father,先初始化:每个数组的下标与它的值相等father[i]=i,
在这里插入图片描述
假如输入1和3,表示1城市到3城市是联通的(1->3),先判断father[i]是否等于i,如果相等就将下标为1的值修改为3,即father[1]=3;否则根据father[i]存的值查找数组下标为father[i]的数,一直到查到father[i]=i,再father[i]=b;
在这里插入图片描述假如再输入1和5,表示1城市到5城市是联通的(1->5).还是一样先判断father[i]是否等于i,显然不等,就查找father[1]的值,值为3,所以查找father[3],再判断father[3]是否等于3,这里是等于,所以将father[3]赋值为5,否则继续查找。
在这里插入图片描述
当所有的用例输入完后,father数组的每个元素也都有修改后的值了,这时候,遍历数组,记录father[i]仍然等于i的个数,得到的就是答案.

✈️✈️查函数代码(Find)

在这里插入图片描述

int Find(int x)
{
	int t = x;
	while (t != father[t])
	{
		t = father[t];
	}
	return t;
}

✈️✈️并函数代码(Union)

在这里插入图片描述

void Union(int x, int y)
{
	int Ax = Find(x);
	int Ay = Find(y);
	if (Ax != Ay)
	{
		father[Ax] = Ay;
	}
}

下面引入俩道题,先看杭电1213:

✈️✈️杭电1213:

在这里插入图片描述

题意:有人过生日,邀请朋友参加,大家一起吃饭。不认识的人不呆在一桌不好。如果A认识B,B认识C,那么A也被认为是和C认识,能够待在同一桌。
问题:最少要多少张桌子?

这个问题其实转化过来就是问有多少个联通的。

代码段:

#include<iostream>
using namespace std;
const int N = 1e3 + 10;
int father[N];
int Find(int x)
{
	int t = x;
	while (t != father[t])
	{
		t = father[t];
	}
	return t;
}

void Union(int x, int y)
{
	int Ax = Find(x);
	int Ay = Find(y);
	if (Ax != Ay)
	{
		father[Ax] = Ay;
	}
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n, m;
		cin >> n >> m;
		for (int i = 1; i < n + 1; i++)
		{
			father[i] = i;
		}
		while (m--)
		{
			int x, y;
			cin >> x >> y;
			Union(x, y);
		}
		int count = 0;
		for (int i = 1; i < n+1; i++)
		{
			if (father[i] == i)
			{
				count++;
			}
		}
		cout << count << endl;
	}
	return 0;
}

✈️✈️杭电1232:

在这里插入图片描述

题意:要使整个图连通,至少还需几条边?
答案就是连通的个数减去1
代码和上面是一样的,最后答案为count-1;

😜😜最后的话

好啦,这篇博客到此结束啦,
在这里插入图片描述
该去吃中饭咯😃😃,下午有节选修课🤒🤒,今晚要学AVL啦❤️

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值