算法训练之并查集

【模板】并查集

题目描述

如题,现在有一个并查集,你需要完成合并和查询操作。

输入格式

第一行包含两个整数 N , M N,M N,M ,表示共有 N N N 个元素和 M M M 个操作。

接下来 M M M 行,每行包含三个整数 Z i , X i , Y i Z_i,X_i,Y_i Zi,Xi,Yi

Z i = 1 Z_i=1 Zi=1 时,将 X i X_i Xi Y i Y_i Yi 所在的集合合并。

Z i = 2 Z_i=2 Zi=2 时,输出 X i X_i Xi Y i Y_i Yi 是否在同一集合内,是的输出
Y ;否则输出 N

输出格式

对于每一个 Z i = 2 Z_i=2 Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N

样例 #1

样例输入 #1

4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4

样例输出 #1

N
Y
N
Y

提示

对于 30 % 30\% 30% 的数据, N ≤ 10 N \le 10 N10 M ≤ 20 M \le 20 M20

对于 70 % 70\% 70% 的数据, N ≤ 100 N \le 100 N100 M ≤ 1 0 3 M \le 10^3 M103

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 4 1\le N \le 10^4 1N104 1 ≤ M ≤ 2 × 1 0 5 1\le M \le 2\times 10^5 1M2×105 1 ≤ X i , Y i ≤ N 1 \le X_i, Y_i \le N 1Xi,YiN Z i ∈ { 1 , 2 } Z_i \in \{ 1, 2 \} Zi{1,2}

题解

并查集操作

并查集一共有两个常见的操作

  • 查找
    由于规定同一个集合中存在一个根节点,因此查找操作就是对给定的节点寻找根节点(也就是寻找父亲)
int findFather(int x)
{
	while(x!=father[x])x=father[x];
	return x;
}
  • 合并

就是将两个无关的集合进行合并,首先先要判断两个集合元素是否属于同一个集合当中,也就是根节点是否相同,合并的过程一般就是把其中一个集合的根节点的父亲指向另一个集合的根节点

void Union(int a,int b)
{
int faA=findFather(a);
int faB=findFather(b); 
if(faA!=faB)father[faA]=faB;
}

完整题解

#include<iostream>
const int N=100010;
using namespace std;
int p[N];
int find(int x)
{
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;++i)p[i]=i;//初始化操作,自己是自己的父亲
    
    while(m--)
    {
        int op,x,y;
        scanf("%d%d%d",&op,&x,&y);
        if(op==1)
        {
            p[find(x)]=find(y);//将两个集合合并
        }
        else
        {//查看两个集合是否相同的父节点
            if(find(x)==find(y))puts("Y");
            else puts("N");
        }
    }
    return 0;
}

路径压缩

路径压缩是并查集当中的一个常见操作,由于目标是找到每个节点的根节点,那么就可以把当前查询节点的路径上所有的结点的父亲都指向根节点
请添加图片描述
这样做的好处就在于可以将访问的时间下降到 O ( 1 ) O(1) O(1)

int findFather(int x)
{
	int a=x;//将原先的x保存
	while(x!=father[x])x=father[x];
	while(a!=father[a])
	{
	int z=a;
	a=father[a];
	father[z]=x;//原先的结点a的父亲改为根节点x
	}
	return x;//返回根节点
}

参考内容

  • 算法笔记,推荐大家看一下
  • 原题来自洛谷
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以按照以下步骤训练自己的数据集使用ArcFace模型: 1. 收集和准备数据集:收集具有不同身份的人脸图像,并为每个人脸分配唯一的标签。确保每个人脸图像的质量和清晰度较高。 2. 数据预处理:对数据集进行预处理以提高模型的性能。这包括裁剪人脸图像、调整大小、灰度化、直方图均衡化等。 3. 构建训练集和验证集:将数据集划分为训练集和验证集,通常采用80%的数据用于训练,20%的数据用于验证。 4. 构建ArcFace模型:使用深度学习框架(如TensorFlow或PyTorch)构建ArcFace模型。ArcFace模型的核心是使用余弦相似度来度量人脸特征之间的距离。 5. 定义损失函数:ArcFace模型需要定义合适的损失函数,常用的是ArcFace Loss函数,它可以增加类间的差异并减小类内的差异。 6. 执行训练过程:使用训练集对构建的ArcFace模型进行训练。在每个训练步骤中,输入人脸图像并计算损失,然后使用反向传播算法更新模型的权重。 7. 评估模型性能:使用验证集评估模型的性能。可以计算准确率、查准率、查全率等指标来评估模型在人脸识别任务上的性能。 8. 调优和优化:根据评估结果,根据需要对模型进行调优和优化。可以尝试调整超参数、增加数据量、数据增强等方法来提高模型性能。 9. 测试模型:对训练好的模型进行测试,使用新的人脸图像进行人脸识别,观察模型的准确度和鲁棒性。 以上是训练自己数据集使用ArcFace模型的一般步骤。具体实施时,您可能需要参考相关的深度学习框架文档和教程,并根据您的具体需求进行调整和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值