并查集

并查集是一种用来管理元素分组情况的数据结构。一般用来检查图的连通性。并查集通过树形结构实现,每一个元素对应一个节点,每一个组对应一棵树。


(1)初始化


准备n个节点来表示n个元素,最开始没有边。


(2)合并


从一个组的根向另一个组的根连边,这样两棵树就成了一棵树。


(3)查询


目的是为了知道两个节点是否属于同一个组,我们沿着树向上走,来查询这棵树的根是什么。如果两个节点走到了同一个根,则它们是同一组。


(4)退化


树形结构如果发生退化,那么复杂度就会很高,因此需要避免。我们在合并时,如果两棵树的高度不同,则高度小的向高度大的树连边。


(5)路径压缩


对于每个节点,一旦向上走到了根结点,就把该节点直接和根节点相连。


(6)实现

CODE

#define MAXN 100
class DisjointSet
{
private:
	 int par[MAXN];
	int rank[MAXN];
public:
	void init(int n)
	{
		for (int i = 0; i < n; ++i)
		{
			par[i] = i;
			rank[i] = 0;
		}
	}

	 int find(int x)
	{
		if (par[x] == x)
			return x;
		else
			return par[x] = find(par[x]);
	}
	
	 void unite(int x, int y)
	{
		x = find(x);
		y = find(y);

		if (x == y)return;
		if (rank[x] < rank[y])
			par[x] = y;
		else
		{
			par[y] = x;
			if (rank[x] == rank[y])++rank[x];
		}
	}

	 bool same(int x, int y)
	{
		return find(x) == find(y);
	}
};

实战应用:

POJ1182

CODE

void solve1182()
{
	int ans = 0;
	DisjointSet D;
	for (int i = 0; i < K; ++i)
	{
		int t = T[i];
		int x = X[i] - 1, y = Y[i] - 1;
		if (x < 0 || N <= x || y < 0 || N <= y)
		{
			++ans; continue;
		}

		if (t == 1)
		{
			if (D.same(x, y + N) || D.same(x, y + N * 2))
				++ans;
			else
			{
				D.unite(x, y);//x-A union y-A
				D.unite(x + N, y + N);
				D.unite(x + N * 2, y + N * 2);
			}
		}
		else
		{
			if (D.same(x, y) || D.same(x, y + N * 2))
				++ans;
			else
			{
				D.unite(x + N, y);
				D.unite(x, y + N * 2);
				D.unite(x + N * 2, y);
			}
		}
	}
	printf("%d\n", ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值