数据结构——查并集

关于查并集也是浅浅的了解了一点,查并集是将一些不相交的集合合并,形成一条线或者形成一个散射图等。
大体上分为3部。
1、初始化
2、合并
3、查找
初始化就是将每一个点看成一个集合。

for(int i=1;i<=n;i++)
s[i]=i;

合并是把两个相关的点录入s[n]数组

void union_s(int x,int y)
{
int xx=find_s(x);
int yy=find_s(y);
if(xx!=yy)s[x]=y;
}

第三步查找就是给定一个数通过递归来找到他的根结点

int find_s(int n)
{
  while(pre[n] != n)			
		 n= s[n];				
	return n;	
}

但是这种方法会导致路径过长,所以我们在查找的时候可以进行优化,把路径进行压缩,使他们都指向根结点。

int find_s(int n)
{
  if(n!=s[n])s[n]=find_s(s[n]);
  return s[n];
}

这么说有点浅显直接上题

有n个人一起吃饭,认识的人一桌(只要有一个认识的即可),例如:a和b认识,b和c认识,a/b/c就可以在一桌。试问需要几个桌子;
第一行输入n和m表示n个人和共有m组两两认识
第二行到第m+1行输入a和b两个数表示A和B两两认识
最终输出共有几个桌

分析:
这其实就是简单地查并集问题只要找到有几个根结点即可
代码:

#include <iostream>
#include<fstream>
#include <vector>
#include <utility>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <cstdio>
#include <fstream>
#include <set>
#include<stdio.h>
#include<bits/stdc++.h>
#include <iomanip>
#include<cmath>
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
#include<iostream>
using namespace std;

int n;
int s[1000010],a[100010]={0};
void inti(int n)
{
    for(int i=1;i<=n;i++)
        s[i]=i;
}
int find_s(int a)
{
    if(s[a]==a) return a;
     return s[a]=find_s(s[a]);
}
/* find_s函数查找每一个数的根结点并赋值为根结点的值 */
void union_s(int x,int y)
{
    int xx=find_s(x);
    int yy=find_s(y);
    if(xx!=yy)s[xx]=yy;
}
int main()
{
    int x,y,l;
    cin>>n>>l;//输入n个人和l组关系
    inti(n); //对每个人进行初始化,每个人都是自己的根结点
    for(int i=1;i<=l;i++)
    {
        cin>>x>>y;
        union_s(x,y); //将两个人的关系合并
    }
    int sum=0;
    for(int i=1;i<=n;i++)
        a[find_s(i)]=1; //查找这n个人的根结点,并将根结点赋值,不是根结点的不进行赋值
    for(int i=1;i<=n;i++)
    if(a[i])sum++;//判断根节点的个数从而判断需要几个桌子
    cout<<sum<<endl;
    return 0;
}
总结:

查并集就是来求数据之间关系的,固定的模板还算是比较简单和比较容易理解的。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨晓翔同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值