并查集删点总结

并查集删点操作需要借助虚点,实际上也就是一个映射罢了。

通过index[i]表示i点经过映射后的编号,规定访问一个节点时只能通过它的编号index[i]来访问,初始时将各点的index[i]置为i,表示还未进行删点操作时都映射到本身,在删除点i时,将点i映射到一个虚节点上,即index[i] = m(m为虚节点编号),同时father[index[i]] = index[i] (表示删除点i后i点独立),之后所有涉及到点i的操作都用index[i]来代替,即m。

这样的好处在于find()函数不需要修改,且一定能够保证被删点所在连通块依然连通。

例如下图中,删除了2号点,实际上并没有真的删除它,而是把2号点映射到了5号点,之后每次使用2号点都用5号点来代替,而原来的2号节点不可能再被访问到,变成了垃圾节点。

以​Junk-Mail Filter HDU - 2473为例,放一个模板:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring> 
using namespace std;
//为了删点(例如i点)后不破坏连通性,fa[i]不能改变,因为它是一座桥梁 
//index[i]表示将i映射到index[i],index[i]是虚节点下标,每次merge和find都要先把i通过index映射一下 
//fa数组多开了一倍,为可能出现的虚节点开辟空间
//这样的好处是merge和find函数都不用改变,只是调用的时候传映射过的值就可以了 
int n, m, num;
int fa[1100005], index[100005];
bool vis[1100005];

void init()
{
	for(int i = 0; i <= n-1; i++)
		fa[i] = index[i] = i;//需要对index也初始化,表示一开始都映射到本身 
	num = 0;//表示开了几个虚节点 
 } 

int find(int x)
{
	if(fa[x] == x)
		return x;
	return fa[x] = find(fa[x]);
}

void merge(int x, int y)
{
	int fx = find(x), fy = find(y);
	if(fx != fy)
		fa[fx] = fy;
}

void del(int x)//本质上是改变i点的映射 
{
	fa[n+num] = n+num;//自己独立出来 
	index[x] = n+num;
	num++;
}

signed main()
{
	int t = 0;
	while(~scanf("%d%d", &n ,&m))
	{
		t++;
		if(n == 0 && m == 0)
			break;
		init();
		char op[2];
		int a, b;
		for(int i = 1; i <= m; i++)
		{
			scanf("%s", op);
			if(op[0] == 'M')
			{
				scanf("%d%d", &a, &b);
				merge(index[a], index[b]);
			}
			else
			{
				scanf("%d", &a);
				del(a);//这里不可以再取index了,因为index是对原始的n个数映射 
			}
		}
		int ans = 0;
		memset(vis, false, sizeof vis);
		for(int i = 0; i <= n-1; i++)//只能这么求,统计有多少个不同的根节点 
		{
			if(!vis[find(index[i])])
				ans++, vis[find(index[i])] = true;
		}
//求连通块数,假如只看fa[x]==x,1->2->3,分别删1,2,3,会有问题 
//		for(int i = 0; i <= n-1; i++)//也不能这样求,比如1->2,删根节点2,会有错误 
//			if(fa[index[i]] == index[i])
//				ans++; 
		printf("Case #%d: %d\n", t, ans);
	}
	 
    return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在使用MFC连接MySQL数据库时,可以通过以下几个步骤进行增删改查操作。 首先,需要添加MySQL的头文件和库文件到MFC项目中。可以在项目属性中配置附加包含目录和附加库目录,并将mysqlcppconn.lib添加到链接器中。 接下来,在MFC应用程序中创建一个数据库连接对象,并通过该对象建立与MySQL数据库的连接。连接对象可以使用mysql::cppconn::DriverManage的getConnection()方法来获取,需要指定数据库的连接参数,如数据库地址、用户名、密码等。连接成功后,可以将该连接对象用于后续的操作。 要进行增删改查操作,可以使用SQL语句来执行相关操作。通过连接对象的createStatement()方法创建一个Statement对象,然后使用该对象的execute()方法执行SQL语句。例如,可以使用INSERT语句进行插入数据,使用DELETE语句进行删除数据,使用UPDATE语句进行更新数据,使用SELECT语句进行查询数据。 执行SQL语句后,可以通过Statement对象的getResultSet()方法获取查询结果集。然后可以使用ResultSet对象的相关方法来获取查询结果的数据。 最后,记得在操作完成后关闭数据库连接,可以通过连接对象的close()方法实现。 总结起来,使用MFC连接MySQL数据库进行增删改查操作的步骤包括:建立数据库连接、创建Statement对象、执行SQL语句、获取查询结果集、关闭数据库连接等。通过这些步骤可以实现MFC与MySQL的数据交互操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值